diff --git a/.appveyor.yml b/.appveyor.yml new file mode 100644 index 000000000..7ca7d58c4 --- /dev/null +++ b/.appveyor.yml @@ -0,0 +1,27 @@ +clone_depth: 1 +version: "{build}" +image: Visual Studio 2017 +platform: + - x86 + - x64 +environment: + matrix: + - compiler: msvc +install: + - vcpkg install --triplet %PLATFORM%-windows --recurse fftw3 libsamplerate libsndfile sdl2 + - nuget install clcache -Version 4.1.0 +build_script: + - cd %APPVEYOR_BUILD_FOLDER% + - mkdir build + - cd build + - ps: $env:CMAKE_PLATFORM="$(if ($env:PLATFORM -eq 'x64') { 'x64' } else { '' })" + - ps: $env:QT_SUFFIX="$(if ($env:PLATFORM -eq 'x64') { '_64' } else { '' })" + - cmake -DUSE_COMPILE_CACHE=ON -DCACHE_TOOL=%APPVEYOR_BUILD_FOLDER%/clcache.4.1.0/clcache-4.1.0/clcache.exe -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_PREFIX_PATH=c:/Qt/5.12/msvc2017%QT_SUFFIX%;c:/tools/vcpkg/installed/%PLATFORM%-windows -DCMAKE_GENERATOR_PLATFORM="%CMAKE_PLATFORM%" .. + - cmake --build . -- /maxcpucount:4 + - cmake --build . --target tests + - cmake --build . --target package +artifacts: + - path: 'build\lmms-*.exe' + name: Installer +cache: + - c:/tools/vcpkg/installed diff --git a/.circleci/config.yml b/.circleci/config.yml index 4b370aed9..a3be541b5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -12,6 +12,18 @@ shared: key: ccache-{{ arch }}-{{ .Environment.CIRCLE_JOB }}-{{ .Branch }}-{{ .BuildNum }} paths: - ~/.ccache + restore_homebrew_cache: &restore_homebrew_cache + restore_cache: + keys: + - homebrew-{{ arch }}-{{ .Environment.CIRCLE_JOB }}-{{ .Branch }} + - homebrew-{{ arch }}-{{ .Environment.CIRCLE_JOB }} + - homebrew-{{ arch }} + save_homebrew_cache: &save_homebrew_cache + save_cache: + key: homebrew-{{ arch }}-{{ .Environment.CIRCLE_JOB }}-{{ .Branch }}-{{ .BuildNum }} + paths: + - ~/Library/Caches/Homebrew + - /usr/local/Homebrew ccache_stats: &ccache_stats run: @@ -28,6 +40,16 @@ shared: name: Initialize command: | 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 @@ -54,6 +76,18 @@ jobs: ../cmake/build_win32.sh make lmms make + - 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: @@ -71,11 +105,23 @@ jobs: mkdir build && cd build ../cmake/build_win64.sh make + - run: + name: Build tests + command: cd build && make tests + - run: + name: Build installer + command: | + cd build + make package + cp ./lmms-*.exe /tmp/artifacts/ + - store_artifacts: + path: /tmp/artifacts/ + destination: / - *ccache_stats - *save_cache linux.gcc: docker: - - image: lmmsci/linux.gcc:18.04 + - image: lmmsci/linux.gcc:16.04 environment: <<: *common_environment steps: @@ -84,7 +130,10 @@ jobs: - *restore_cache - run: name: Configure - command: mkdir build && cd build && cmake .. $CMAKE_OPTS -DCMAKE_INSTALL_PREFIX=./install + command: | + source /opt/qt5*/bin/qt5*-env.sh || true + mkdir build && cd build + cmake .. $CMAKE_OPTS -DCMAKE_INSTALL_PREFIX=./install - run: name: Build command: cd build && make @@ -100,7 +149,7 @@ jobs: command: | cd build make install - make appimage + make appimage || (cat appimage.log && false) cp ./lmms-*.AppImage /tmp/artifacts/ - store_artifacts: path: /tmp/artifacts/ @@ -117,10 +166,53 @@ jobs: - run: name: Shellcheck command: shellcheck $(find "./cmake/" -type f -name '*.sh' -o -name "*.sh.in") + macos: + environment: + <<: *common_environment + macos: + xcode: "9.3.1" + steps: + - checkout + - *init + - *restore_homebrew_cache + - *restore_cache + - run: + name: Install Homebrew dependencies + command: brew update && brew install ccache fftw cmake pkg-config libogg libvorbis lame libsndfile libsamplerate jack sdl libgig libsoundio stk fluid-synth portaudio fltk qt5 carla + - run: + name: Install nodejs dependencies + command: npm install -g appdmg + - run: + name: Building + command: | + mkdir build && cd build + cmake .. -DCMAKE_INSTALL_PREFIX="../target" -DCMAKE_PREFIX_PATH="$(brew --prefix qt5)" $CMAKE_OPTS -DUSE_WERROR=OFF + make + - run: + name: Build tests + command: cd build && make tests + - run: + name: Run tests + command: build/tests/tests + - run: + name: Build DMG + command: | + cd build + make install + make dmg + cp ./lmms-*.dmg /tmp/artifacts/ + - store_artifacts: + path: /tmp/artifacts/ + destination: / + - *save_cache + - *save_homebrew_cache + + workflows: version: 2 build-and-test: jobs: + - macos - mingw32 - mingw64 - linux.gcc diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..2d4a9f975 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,5 @@ +root = true + +[*] +indent_style = tab +tab_width = 4 diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 000000000..8a8b03635 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +custom: https://lmms.io/get-involved/#donate diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..2c22146ae --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,30 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: bug +assignees: '' + +--- + +# Please search the issue tracker for existing bug reports before submitting your own. Delete this line to confirm no similar report has been posted yet. + +### Bug Summary + +#### Steps to reproduce + +#### Expected behavior + +#### Actual behavior + +#### Screenshot + +#### LMMS version used + +#### Logs +
+ Click to expand +
+
+
+
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 000000000..2c51f276e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,4 @@ +contact_links: +- name: Get help on Discord + url: https://lmms.io/chat/ + about: Need help? Have a question? Reach out to other LMMS users on our Discord server! diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 000000000..f9a0ae192 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,18 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: enhancement +assignees: '' + +--- + +# Please search the issue tracker for existing feature requests before submitting your own. Delete this line to confirm no similar request has been posted yet. + +### Enhancement Summary + +#### Justification + +#### Mockup + + diff --git a/.gitignore b/.gitignore index aa4f17ab8..771eba607 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ /build /target .*.sw? +.DS_Store *~ /CMakeLists.txt.user /plugins/zynaddsubfx/zynaddsubfx/ExternalPrograms/Controller/Makefile diff --git a/.gitmodules b/.gitmodules index 94530a197..28d6c5d46 100644 --- a/.gitmodules +++ b/.gitmodules @@ -28,3 +28,9 @@ [submodule "src/3rdparty/weakjack/weakjack"] path = src/3rdparty/weakjack/weakjack url = https://github.com/x42/weakjack.git +[submodule "src/3rdparty/mingw-std-threads"] + path = src/3rdparty/mingw-std-threads + url = https://github.com/meganz/mingw-std-threads.git +[submodule "doc/wiki"] + path = doc/wiki + url = https://github.com/lmms/lmms.wiki.git diff --git a/.mailmap b/.mailmap index 0ff7c15dd..14d4754ce 100644 --- a/.mailmap +++ b/.mailmap @@ -1,5 +1,5 @@ Alexandre Almeida -Tobias Doerffel +Tobias Junghans Dave French Paul Giblock Paul Giblock @@ -26,3 +26,8 @@ Thomas Clark Thomas Clark anonymous Locale updater <> grejppi +Johannes Lorenz +Johannes Lorenz <1042576+JohannesLorenz@users.noreply.github.com> +Noah Brecht +Olivier Humbert +Hussam al-Homsi Hussam Eddin Alhomsi diff --git a/.travis.yml b/.travis.yml index 5cf25ac71..f94aa0846 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,28 +4,44 @@ dist: trusty sudo: required cache: directories: - - apt_mingw_cache + - $HOME/apt_mingw_cache - $HOME/.ccache + - $HOME/pbuilder-bases 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 + - env: TARGET_OS=debian-sid TARGET_ARCH=i386 + git: + depth: false + - compiler: clang + env: TARGET_OS=debian-sid + 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 install: ${TRAVIS_BUILD_DIR}/.travis/install.sh script: ${TRAVIS_BUILD_DIR}/.travis/script.sh after_script: ${TRAVIS_BUILD_DIR}/.travis/after_script.sh -before_deploy: make package +before_deploy: + - if [ "$TARGET_OS" != debian-sid ]; then make package; fi deploy: provider: releases api_key: secure: d4a+x4Gugpss7JK2DcHjyBZDmEFFh4iVfKDfITSD50T6Mc6At4LMgojvEu+6qT6IyOY2vm3UVT6fhyeuWDTRDwW9tfFlaHVA0h8aTRD+eAXOA7pQ8rEMwQO3+WCKuKTfEqUkpL4wxhww8dpkv54tqeIs0S4TBqz9tk8UhzU7XbE= - file: lmms-${TRAVIS_TAG:1}-$TARGET_OS.exe + file_glob: true + file: + - lmms-${TRAVIS_TAG:1}-$TARGET_OS.exe + - /var/cache/pbuilder/result/lmms_*.tar.xz skip_cleanup: true on: tags: true all_branches: true - condition: '("$TARGET_OS" = win??)' + condition: '"$TARGET_DEPLOY" = True' repo: LMMS/lmms diff --git a/.travis/debian_pkgs.sha256 b/.travis/debian_pkgs.sha256 new file mode 100644 index 000000000..ed4e11737 --- /dev/null +++ b/.travis/debian_pkgs.sha256 @@ -0,0 +1,3 @@ +314ef4af137903dfb13e8c3ef1e6ea56cfdb23808d52ec4f5f50e288c73610c5 pbuilder_0.229.1_all.deb +fa82aa8ed3055c6f6330104deedf080b26778295e589426d4c4dd0f2c2a5defa debootstrap_1.0.95_all.deb +2ef4c09f7841b72f93412803ddd142f72658536dbfabe00e449eb548f432f3f8 debian-archive-keyring_2017.7ubuntu1_all.deb diff --git a/.travis/linux..install.sh b/.travis/linux..install.sh index ab4fba263..2f1262d07 100755 --- a/.travis/linux..install.sh +++ b/.travis/linux..install.sh @@ -23,4 +23,4 @@ sudo apt-get install -y $PACKAGES sudo add-apt-repository -y ppa:kxstudio-debian/libs sudo add-apt-repository -y ppa:kxstudio-debian/apps sudo apt-get update -sudo apt-get install -y carla-git +sudo apt-get install -y carla diff --git a/.travis/linux..script.sh b/.travis/linux..script.sh index 354f1a876..e75b827ac 100755 --- a/.travis/linux..script.sh +++ b/.travis/linux..script.sh @@ -5,5 +5,11 @@ source /opt/qt59/bin/qt59-env.sh set -e +mkdir build +cd build + # shellcheck disable=SC2086 cmake -DUSE_WERROR=ON -DCMAKE_INSTALL_PREFIX=../target $CMAKE_FLAGS .. +make -j4 +make tests +./tests/tests diff --git a/.travis/linux.debian-sid.before_install.sh b/.travis/linux.debian-sid.before_install.sh new file mode 100755 index 000000000..89ee51523 --- /dev/null +++ b/.travis/linux.debian-sid.before_install.sh @@ -0,0 +1,2 @@ +#!/bin/sh +sudo apt-get update -qq diff --git a/.travis/linux.debian-sid.install.sh b/.travis/linux.debian-sid.install.sh new file mode 100755 index 000000000..ef8368822 --- /dev/null +++ b/.travis/linux.debian-sid.install.sh @@ -0,0 +1,17 @@ +#!/bin/sh +set -e + +sudo apt-get install -y \ + dpkg \ + pbuilder + +# work around a pbuilder bug which breaks ccache +# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=666525 +# and also missing signing keys in Trusty's debian-archive-keyring +cd /tmp +wget http://archive.ubuntu.com/ubuntu/pool/main/p/pbuilder/pbuilder_0.229.1_all.deb +wget http://archive.ubuntu.com/ubuntu/pool/main/d/debootstrap/debootstrap_1.0.95_all.deb +wget http://archive.ubuntu.com/ubuntu/pool/universe/d/debian-archive-keyring/debian-archive-keyring_2017.7ubuntu1_all.deb +sha256sum -c "$TRAVIS_BUILD_DIR/.travis/debian_pkgs.sha256" +sudo dpkg -i pbuilder_0.229.1_all.deb debootstrap_1.0.95_all.deb debian-archive-keyring_2017.7ubuntu1_all.deb +cd "$OLDPWD" diff --git a/.travis/linux.debian-sid.script.sh b/.travis/linux.debian-sid.script.sh new file mode 100755 index 000000000..9b8db416c --- /dev/null +++ b/.travis/linux.debian-sid.script.sh @@ -0,0 +1,72 @@ +#!/bin/bash +set -e + +: "${TARGET_ARCH:=amd64}" + +BASETGZ="$HOME/pbuilder-bases/debian-sid-$TARGET_ARCH.tgz" +MIRROR=http://cdn-fastly.deb.debian.org/debian +KEYRING=/usr/share/keyrings/debian-archive-keyring.gpg + +if [ -z "$TRAVIS_TAG" ] +then + sudo \ + sh -c "echo CCACHEDIR=$HOME/.ccache >> /etc/pbuilderrc" +fi + +if [ "$CC" = clang ] +then + sudo sh -c "echo EXTRAPACKAGES=clang >> /etc/pbuilderrc" +fi + +if [ ! -e "$BASETGZ.stamp" ] +then + mkdir -p "$HOME/pbuilder-bases" + sudo pbuilder --create --basetgz "$BASETGZ" --mirror $MIRROR \ + --distribution sid --architecture $TARGET_ARCH \ + --debootstrapopts --variant=buildd \ + --debootstrapopts --keyring=$KEYRING \ + --debootstrapopts --include=perl + touch "$BASETGZ.stamp" +else + sudo pbuilder --update --basetgz "$BASETGZ" +fi + +sync_version() { + local VERSION + local MMR + local STAGE + local EXTRA + + VERSION=$(git describe --tags --match v[0-9].[0-9].[0-9]*) + VERSION=${VERSION#v} + MMR=${VERSION%%-*} + case $VERSION in + *-*-*-*) + VERSION=${VERSION%-*} + STAGE=${VERSION#*-} + STAGE=${STAGE%-*} + EXTRA=${VERSION##*-} + VERSION=$MMR~$STAGE.$EXTRA + ;; + *-*-*) + VERSION=${VERSION%-*} + EXTRA=${VERSION##*-} + VERSION=$MMR.$EXTRA + ;; + *-*) + STAGE=${VERSION#*-} + VERSION=$MMR~$STAGE + ;; + esac + + sed "1 s/@VERSION@/$VERSION/" -i debian/changelog + echo "Set Debian version to $VERSION" +} + +sync_version + +DIR="$PWD" +cd .. +dpkg-source -b "$DIR" +env -i CC="$CC" CXX="$CXX" sudo pbuilder --build --debbuildopts "--jobs=auto" \ + --basetgz "$BASETGZ" ./*.dsc diff --git a/.travis/linux.win.download.sh b/.travis/linux.win.download.sh index 215d4eb93..2f914f94e 100755 --- a/.travis/linux.win.download.sh +++ b/.travis/linux.win.download.sh @@ -2,7 +2,7 @@ set -e -CACHE_DIR=$TRAVIS_BUILD_DIR/apt_mingw_cache/$1 +CACHE_DIR=$HOME/apt_mingw_cache/$1 mkdir -p "$CACHE_DIR" pushd "$CACHE_DIR" diff --git a/.travis/linux.win32.script.sh b/.travis/linux.win32.script.sh index d89cf1b75..6e930fd9b 100755 --- a/.travis/linux.win32.script.sh +++ b/.travis/linux.win32.script.sh @@ -1,6 +1,11 @@ #!/usr/bin/env bash - set -e +mkdir build +cd build + export CMAKE_OPTS="$CMAKE_FLAGS -DUSE_WERROR=ON" ../cmake/build_win32.sh + +make -j4 +make tests diff --git a/.travis/linux.win64.script.sh b/.travis/linux.win64.script.sh index 931e23d8d..d81fa9b58 100755 --- a/.travis/linux.win64.script.sh +++ b/.travis/linux.win64.script.sh @@ -1,6 +1,11 @@ #!/usr/bin/env bash - set -e +mkdir build +cd build + export CMAKE_OPTS="$CMAKE_FLAGS -DUSE_WERROR=ON" ../cmake/build_win64.sh + +make -j4 +make tests diff --git a/.travis/osx..install.sh b/.travis/osx..install.sh index 4f92db746..e3dd670bf 100755 --- a/.travis/osx..install.sh +++ b/.travis/osx..install.sh @@ -2,7 +2,7 @@ set -e -PACKAGES="cmake pkg-config libogg libvorbis lame libsndfile libsamplerate jack sdl libgig libsoundio stk fluid-synth portaudio node fltk qt5" +PACKAGES="cmake pkg-config libogg libvorbis lame libsndfile libsamplerate jack sdl libgig libsoundio stk fluid-synth portaudio node fltk qt5 carla" if "${TRAVIS}"; then PACKAGES="$PACKAGES ccache" @@ -19,4 +19,4 @@ brew install $PACKAGES # fftw tries to install gcc which conflicts with travis brew install fftw --ignore-dependencies -sudo npm install -g appdmg +npm install -g appdmg diff --git a/.travis/osx..script.sh b/.travis/osx..script.sh index 3253f4ed7..373e273f4 100755 --- a/.travis/osx..script.sh +++ b/.travis/osx..script.sh @@ -1,10 +1,16 @@ #!/usr/bin/env bash - set -e +mkdir build +cd build + # Workaround; No FindQt5.cmake module exists CMAKE_PREFIX_PATH="$(brew --prefix qt5)" export CMAKE_PREFIX_PATH # shellcheck disable=SC2086 cmake -DUSE_WERROR=OFF -DCMAKE_INSTALL_PREFIX=../target $CMAKE_FLAGS .. + +make -j4 +make tests +./tests/tests diff --git a/.travis/script.sh b/.travis/script.sh index 9f7e1081f..b723f5dd0 100755 --- a/.travis/script.sh +++ b/.travis/script.sh @@ -8,13 +8,11 @@ if [ "$TYPE" = 'style' ]; then # once it's fixed, it should be enabled again # shellcheck disable=SC2185 # shellcheck disable=SC2046 - shellcheck $(find -O3 "$TRAVIS_BUILD_DIR/.travis/" "$TRAVIS_BUILD_DIR/cmake/" -type f -name '*.sh' -o -name "*.sh.in") + shellcheck $(find -O3 . -maxdepth 3 -type f -name '*.sh' -o -name "*.sh.in") + shellcheck doc/bash-completion/lmms else - mkdir -p build - cd build - export CMAKE_FLAGS="-DCMAKE_BUILD_TYPE=RelWithDebInfo" if [ -z "$TRAVIS_TAG" ]; then @@ -23,32 +21,28 @@ else "$TRAVIS_BUILD_DIR/.travis/$TRAVIS_OS_NAME.$TARGET_OS.script.sh" - make -j4 - - if [[ $TARGET_OS != win* ]]; then - - make tests - tests/tests - - fi - # Package and upload non-tagged builds if [ ! -z "$TRAVIS_TAG" ]; then # Skip, handled by travis deploy instead exit 0 elif [[ $TARGET_OS == win* ]]; then + cd build make -j4 package PACKAGE="$(ls lmms-*win*.exe)" elif [[ $TRAVIS_OS_NAME == osx ]]; then + cd build make -j4 install > /dev/null make dmg PACKAGE="$(ls lmms-*.dmg)" - else + elif [[ $TARGET_OS != debian-sid ]]; then + cd build make -j4 install > /dev/null make appimage PACKAGE="$(ls lmms-*.AppImage)" fi echo "Uploading $PACKAGE to transfer.sh..." - curl --upload-file "$PACKAGE" "https://transfer.sh/$PACKAGE" || true + # Limit the connection time to 3 minutes and total upload time to 5 minutes + # Otherwise the build may hang + curl --connect-timeout 180 --max-time 300 --upload-file "$PACKAGE" "https://transfer.sh/$PACKAGE" || true fi diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c67e9316..2f310d27c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,10 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 3.1.0) +CMAKE_MINIMUM_REQUIRED(VERSION 3.3) PROJECT(lmms) SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules" ${CMAKE_MODULE_PATH}) +SET(LMMS_BINARY_DIR ${CMAKE_BINARY_DIR}) +SET(LMMS_SOURCE_DIR ${CMAKE_SOURCE_DIR}) IF(COMMAND CMAKE_POLICY) CMAKE_POLICY(SET CMP0005 NEW) @@ -13,16 +15,19 @@ IF(COMMAND CMAKE_POLICY) CMAKE_POLICY(SET CMP0050 OLD) ENDIF() CMAKE_POLICY(SET CMP0020 NEW) + CMAKE_POLICY(SET CMP0057 NEW) ENDIF(COMMAND CMAKE_POLICY) +INCLUDE(PluginList) INCLUDE(CheckSubmodules) INCLUDE(AddFileDependencies) INCLUDE(CheckIncludeFiles) INCLUDE(FindPkgConfig) +INCLUDE(GenerateExportHeader) STRING(TOUPPER "${CMAKE_PROJECT_NAME}" PROJECT_NAME_UCASE) -SET(PROJECT_YEAR 2018) +SET(PROJECT_YEAR 2019) SET(PROJECT_AUTHOR "LMMS Developers") SET(PROJECT_URL "https://lmms.io") @@ -31,8 +36,8 @@ 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_STAGE "rc5") +SET(VERSION_RELEASE "1") +SET(VERSION_STAGE "") SET(VERSION_BUILD "0") SET(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_RELEASE}") IF(VERSION_STAGE) @@ -46,7 +51,6 @@ ENDIF() INCLUDE(VersionInfo) INCLUDE(DetectMachine) - OPTION(WANT_ALSA "Include ALSA (Advanced Linux Sound Architecture) support" ON) OPTION(WANT_CALF "Include CALF LADSPA plugins" ON) OPTION(WANT_CAPS "Include C* Audio Plugin Suite (LADSPA plugins)" ON) @@ -58,6 +62,7 @@ OPTION(WANT_MP3LAME "Include MP3/Lame support" ON) OPTION(WANT_OGGVORBIS "Include OGG/Vorbis support" ON) OPTION(WANT_PULSEAUDIO "Include PulseAudio support" ON) OPTION(WANT_PORTAUDIO "Include PortAudio support" ON) +OPTION(WANT_SNDIO "Include sndio support" ON) OPTION(WANT_SOUNDIO "Include libsoundio support" ON) OPTION(WANT_SDL "Include SDL (Simple DirectMedia Layer) support" ON) OPTION(WANT_SF2 "Include SoundFont2 player plugin" ON) @@ -66,12 +71,16 @@ OPTION(WANT_STK "Include Stk (Synthesis Toolkit) support" ON) OPTION(WANT_SWH "Include Steve Harris's LADSPA plugins" ON) OPTION(WANT_TAP "Include Tom's Audio Processing LADSPA plugins" ON) OPTION(WANT_VST "Include VST support" ON) -OPTION(WANT_VST_NOWINE "Include partial VST support (without wine)" OFF) +OPTION(WANT_VST_32 "Include 32-bit VST support" ON) +OPTION(WANT_VST_64 "Include 64-bit VST support" ON) OPTION(WANT_WINMM "Include WinMM MIDI support" OFF) OPTION(WANT_DEBUG_FPE "Debug floating point exceptions" OFF) IF(LMMS_BUILD_APPLE) + # Fix linking on 10.14+. See issue #4762 on github + LINK_DIRECTORIES(/usr/local/lib) + SET(WANT_SOUNDIO OFF) SET(WANT_ALSA OFF) SET(WANT_PULSEAUDIO OFF) SET(WANT_VST OFF) @@ -87,14 +96,13 @@ IF(LMMS_BUILD_WIN32) SET(WANT_ALSA OFF) SET(WANT_JACK OFF) SET(WANT_PULSEAUDIO OFF) - SET(WANT_PORTAUDIO OFF) + SET(WANT_SNDIO OFF) SET(WANT_SOUNDIO OFF) SET(WANT_WINMM ON) SET(LMMS_HAVE_WINMM TRUE) SET(STATUS_ALSA "") SET(STATUS_JACK "") SET(STATUS_PULSEAUDIO "") - SET(STATUS_PORTAUDIO "") SET(STATUS_SOUNDIO "") SET(STATUS_WINMM "OK") SET(STATUS_APPLEMIDI "") @@ -136,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( @@ -153,7 +161,7 @@ SET(QT_LIBRARIES Qt5::Xml ) -IF(LMMS_BUILD_LINUX) +IF(LMMS_BUILD_LINUX AND WANT_VST) FIND_PACKAGE(Qt5 COMPONENTS X11Extras REQUIRED) LIST(APPEND QT_LIBRARIES Qt5::X11Extras) ENDIF() @@ -165,7 +173,7 @@ FIND_PACKAGE(Qt5Test) SET(QT_QTTEST_LIBRARY Qt5::Test) # check for libsndfile -PKG_CHECK_MODULES(SNDFILE REQUIRED sndfile>=1.0.18) +FIND_PACKAGE(SndFile REQUIRED) IF(NOT SNDFILE_FOUND) MESSAGE(FATAL_ERROR "LMMS requires libsndfile1 and libsndfile1-dev >= 1.0.18 - please install, remove CMakeCache.txt and try again!") ENDIF() @@ -212,7 +220,11 @@ ENDIF(WANT_TAP) # check for CARLA IF(WANT_CARLA) - PKG_CHECK_MODULES(CARLA carla-standalone>=1.9.5) + PKG_CHECK_MODULES(CARLA carla-native-plugin) + # look for carla under old name + IF(NOT CARLA_FOUND) + PKG_CHECK_MODULES(CARLA carla-standalone>=1.9.5) + ENDIF() IF(CARLA_FOUND) SET(LMMS_HAVE_CARLA TRUE) SET(STATUS_CARLA "OK") @@ -378,7 +390,6 @@ IF(WANT_JACK) SET(LMMS_HAVE_WEAKJACK TRUE) SET(WEAKJACK_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/src/3rdparty/weakjack/weakjack) SET(STATUS_JACK "OK (weak linking enabled)") - SET(JACK_INCLUDE_DIRS "") # use dlsym instead SET(JACK_LIBRARIES ${CMAKE_DL_LIBS}) ELSE() @@ -386,15 +397,14 @@ IF(WANT_JACK) ENDIF() SET(LMMS_HAVE_JACK TRUE) ELSE(JACK_FOUND) + SET(JACK_INCLUDE_DIRS "") SET(STATUS_JACK "not found, please install libjack0.100.0-dev (or similar) " "if you require JACK support") ENDIF(JACK_FOUND) ENDIF(WANT_JACK) - # check for FFTW3F-library -PKG_CHECK_MODULES(FFTW3F REQUIRED fftw3f>=3.0.0) - +FIND_PACKAGE(FFTW COMPONENTS fftw3f REQUIRED) # check for FLTK FIND_PACKAGE(FLTK) @@ -428,19 +438,20 @@ If(WANT_GIG) ENDIF(WANT_GIG) # check for pthreads -IF(LMMS_BUILD_LINUX OR LMMS_BUILD_APPLE OR LMMS_BUILD_OPENBSD) +IF(LMMS_BUILD_LINUX OR LMMS_BUILD_APPLE OR LMMS_BUILD_OPENBSD OR LMMS_BUILD_FREEBSD) FIND_PACKAGE(Threads) -ENDIF(LMMS_BUILD_LINUX OR LMMS_BUILD_APPLE OR LMMS_BUILD_OPENBSD) +ENDIF(LMMS_BUILD_LINUX OR LMMS_BUILD_APPLE OR LMMS_BUILD_OPENBSD OR LMMS_BUILD_FREEBSD) -# check for sndio (openbsd only, roaraudio won't work yet) -FIND_PACKAGE(Sndio) -IF(LMMS_BUILD_OPENBSD AND SNDIO_FOUND) - SET(LMMS_HAVE_SNDIO TRUE) - SET(STATUS_SNDIO "OK") -ELSE() - SET(STATUS_SNDIO "") - SET(SNDIO_LIBRARY "") -ENDIF() +# check for sndio (roaraudio won't work yet) +IF(WANT_SNDIO) + FIND_PACKAGE(Sndio) + IF(SNDIO_FOUND) + SET(LMMS_HAVE_SNDIO TRUE) + SET(STATUS_SNDIO "OK") + ELSE() + SET(STATUS_SNDIO "") + ENDIF(SNDIO_FOUND) +ENDIF(WANT_SNDIO) # check for WINE IF(WANT_VST) @@ -476,10 +487,10 @@ ELSE() ENDIF(WANT_DEBUG_FPE) # check for libsamplerate -PKG_CHECK_MODULES(SAMPLERATE REQUIRED samplerate>=0.1.8) +FIND_PACKAGE(Samplerate 0.1.8 MODULE REQUIRED) # set compiler flags -IF(CMAKE_CXX_COMPILER_ID MATCHES "GNU|AppleClang") +IF(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") SET(WERROR_FLAGS "-Wall -Werror=unused-function -Wno-sign-compare -Wno-strict-overflow") OPTION(USE_WERROR "Add -werror to the build flags. Stops the build on warnings" OFF) IF(${USE_WERROR}) @@ -539,7 +550,7 @@ ENDIF() # we somehow have to make LMMS-binary depend on MOC-files ADD_FILE_DEPENDENCIES("${CMAKE_BINARY_DIR}/lmmsconfig.h") -IF(CMAKE_CXX_COMPILER_ID MATCHES "GNU|AppleClang") +IF(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") IF(WIN32) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-attributes") ELSE(WIN32) @@ -548,17 +559,7 @@ IF(CMAKE_CXX_COMPILER_ID MATCHES "GNU|AppleClang") ENDIF() # use ccache -OPTION(USE_CCACHE "Use ccache for compilation" OFF) -IF(USE_CCACHE) - FIND_PROGRAM(CCACHE ccache) - IF (CCACHE) - MESSAGE(STATUS "Using ccache found in PATH") - SET_PROPERTY(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE}) - SET_PROPERTY(GLOBAL PROPERTY RULE_LAUNCH_LINK ${CCACHE}) - ELSE() - MESSAGE(WARNING "USE_CCACHE enabled, but no ccache found") - ENDIF() -ENDIF() +include(CompileCache) # make sub-directories ADD_SUBDIRECTORY(cmake) @@ -568,8 +569,8 @@ ADD_SUBDIRECTORY(tests) ADD_SUBDIRECTORY(data) ADD_SUBDIRECTORY(doc) -# post-install tasks -ADD_SUBDIRECTORY(cmake/postinstall) +# install tasks +ADD_SUBDIRECTORY(cmake/install) ADD_CUSTOM_COMMAND(OUTPUT "${CMAKE_BINARY_DIR}/lmms.1.gz" COMMAND gzip -c ${CMAKE_SOURCE_DIR}/doc/lmms.1 > ${CMAKE_BINARY_DIR}/lmms.1.gz @@ -624,6 +625,15 @@ ADD_CUSTOM_TARGET(dist COMMAND tar cjf lmms-${VERSION}-src.tar.bz2 "${TMP}" COMMAND rm -rf "${TMP}") + +# +# add uninstall-target +# +ADD_CUSTOM_TARGET(uninstall + COMMAND ${CMAKE_COMMAND} -DCMAKE_INSTALL_PREFIX="${CMAKE_INSTALL_PREFIX}" -P "${CMAKE_CURRENT_SOURCE_DIR}/cmake/uninstall.cmake" +) + + # # display configuration information # @@ -699,4 +709,10 @@ MESSAGE( "-----------------------------------------------------------------\n" "\n\n") +SET(CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION "${BIN_DIR}") +if(MSVC) + # We can't set this on the install time according to the configuration + SET(CMAKE_INSTALL_DEBUG_LIBRARIES TRUE) + SET(CMAKE_INSTALL_UCRT_LIBRARIES TRUE) +endif() INCLUDE(InstallRequiredSystemLibraries) diff --git a/INSTALL.txt b/INSTALL.txt index fd5392d52..ac5160af6 100644 --- a/INSTALL.txt +++ b/INSTALL.txt @@ -1,16 +1,28 @@ -Building LMMS got quite simple since 0.4.0 as everything is managed -by cmake now. Therefore make sure you have CMake (>= 2.6.0 recommended) and -then run +This project uses git submodules and several are required for a successful +build. If this tarball was NOT provided with submodules (default), some source +dependencies will need to be manually added to src/3rdparty. +If this project WAS provided with submodules, there are detailed dependencies +(e.g. supported compilers, cmake requirements, cross-compilation) at +doc/wiki/Compiling.md including platform-specific build instructions (e.g. +apt-get, dnf, pacman, etc). -mkdir build -cd build -cmake ../ -make -sudo make install +Online documentation: -If your system does not have "sudo", become root with your preferred mechanism -and run the "make install" command. + https://github.com/LMMS/lmms/wiki/ + +Live online chat via Discord (similar to IRC): + + https://lmms.io/chat, Channel #programming + +Basic build steps: + + mkdir build + cd build + cmake ../ + make + sudo make install + # or alternately: su -c 'make install' With the above commands an out-of-tree build is performed. You can also run "cmake ." directly in the root of source tree although this is not recommended. @@ -25,21 +37,31 @@ that are going to be built into LMMS or built as plugins. Install the according libraries and development files if a certain feature is not enabled. Then remove CMakeCache.txt and run cmake again. -If you want to supply an install prefix to cmake, add the flag: +For non-root installs, or to install to a non-standard location, provide an +install prefix to cmake, using the flag: --DCMAKE_INSTALL_PREFIX= + -DCMAKE_INSTALL_PREFIX= -Where can be /usr, /usr/local, /opt, etc. The default is /usr/local. - - - -Building with QT5 - -First of all please note that CMake >= 2.8.11 is required for building with -Qt5 support. +The Compilation tutorial (see docs/wiki/Compilation.md) +specifically uses as "../target" for all non-root installations. This +is strongly recommended if developing a patch or a feature. For root +installations, can be /usr, /usr/local, /opt, etc. For most systems, +the default is /usr/local. If your Qt5 installation does not reside in standard installation paths, -additionally pass e.g. +additionally pass: --DCMAKE_PREFIX_PATH=/opt/qt53/ + -DCMAKE_PREFIX_PATH= +Where is the location to Qt5 installation, usually /opt/qt5/, etc. + +Important wiki sections: + +doc/wiki/Compiling.md: + Dependencies Detailed + - Build Toolchain (cmake) + - Compiler (gcc, clang) + - Libraries (required and optional dependencies) + +doc/wiki/Dependencies-.md + Platform-specific dependencies (Windows, Ubuntu, Fedora, macOS, etc.) diff --git a/cmake/apple/CMakeLists.txt b/cmake/apple/CMakeLists.txt index ff1a8ea46..835d886b9 100644 --- a/cmake/apple/CMakeLists.txt +++ b/cmake/apple/CMakeLists.txt @@ -1,4 +1,4 @@ -SET(MACOSX_BUNDLE_ICON_FILE "lmms.icns") +SET(MACOSX_BUNDLE_ICON_FILE "icon.icns") SET(MACOSX_BUNDLE_GUI_IDENTIFIER "${PROJECT_NAME_UCASE}") SET(MACOSX_BUNDLE_LONG_VERSION_STRING "${VERSION}") SET(MACOSX_BUNDLE_BUNDLE_NAME "${PROJECT_NAME_UCASE}") diff --git a/cmake/apple/dmg_branding.png b/cmake/apple/dmg_branding.png index c14697207..2c6481ecb 100644 Binary files a/cmake/apple/dmg_branding.png and b/cmake/apple/dmg_branding.png differ diff --git a/cmake/apple/dmg_branding@2x.png b/cmake/apple/dmg_branding@2x.png new file mode 100644 index 000000000..7af39fecd Binary files /dev/null and b/cmake/apple/dmg_branding@2x.png differ diff --git a/cmake/apple/icon.icns b/cmake/apple/icon.icns new file mode 100644 index 000000000..3ee7857f4 Binary files /dev/null and b/cmake/apple/icon.icns differ diff --git a/cmake/apple/install_apple.sh.in b/cmake/apple/install_apple.sh.in index 855b5245d..63dc8145e 100644 --- a/cmake/apple/install_apple.sh.in +++ b/cmake/apple/install_apple.sh.in @@ -58,6 +58,17 @@ install_name_tool -change @rpath/libZynAddSubFxCore.dylib \ install_name_tool -change @rpath/libZynAddSubFxCore.dylib \ @loader_path/../../$zynfmk \ "$APP/Contents/$zynlib" + +# Replace @rpath with @loader_path for Carla +# See also plugins/carlabase/CMakeLists.txt +# This MUST be done BEFORE calling macdeployqt +install_name_tool -change @rpath/libcarlabase.dylib \ + @loader_path/libcarlabase.dylib \ + "$APP/Contents/lib/lmms/libcarlapatchbay.so" + +install_name_tool -change @rpath/libcarlabase.dylib \ + @loader_path/libcarlabase.dylib \ + "$APP/Contents/lib/lmms/libcarlarack.so" # Link lmms binary _executables="${_executables} -executable=$APP/Contents/$zynbin" @@ -79,6 +90,28 @@ done # shellcheck disable=SC2086 macdeployqt "$APP" $_executables +# Carla is a standalone plugin. Remove library, look for it side-by-side LMMS.app +# This MUST be done AFTER calling macdeployqt +# +# For example: +# /Applications/LMMS.app +# /Applications/Carla.app +carlalibs=$(echo "@CARLA_LIBRARIES@"|tr ";" "\n") + +# Loop over all libcarlas, fix linking +for file in "$APP/Contents/lib/lmms/"libcarla*; do + _thisfile="$APP/Contents/lib/lmms/${file##*/}" + for lib in $carlalibs; do + _oldpath="../../Frameworks/lib${lib}.dylib" + _newpath="Carla.app/Contents/MacOS/lib${lib}.dylib" + # shellcheck disable=SC2086 + install_name_tool -change @loader_path/$_oldpath \ + @executable_path/../../../$_newpath \ + "$_thisfile" + rm -f "$APP/Contents/Frameworks/lib${lib}.dylib" + done +done + # Cleanup rm -rf "$APP/Contents/bin" echo -e "\nFinished.\n\n" diff --git a/cmake/apple/lmms.icns b/cmake/apple/lmms.icns deleted file mode 100644 index e54187b5c..000000000 Binary files a/cmake/apple/lmms.icns and /dev/null differ diff --git a/cmake/apple/lmms.plist.in b/cmake/apple/lmms.plist.in index 10ff7a996..88fe0b0bf 100644 --- a/cmake/apple/lmms.plist.in +++ b/cmake/apple/lmms.plist.in @@ -147,5 +147,7 @@ NSApplication NSHighResolutionCapable True + NSRequiresAquaSystemAppearance + False diff --git a/cmake/apple/package_apple.json.in b/cmake/apple/package_apple.json.in index 76c487599..1d1147cbf 100644 --- a/cmake/apple/package_apple.json.in +++ b/cmake/apple/package_apple.json.in @@ -1,9 +1,9 @@ { "title": "@MACOSX_BUNDLE_BUNDLE_NAME@ @MACOSX_BUNDLE_LONG_VERSION_STRING@", "background": "@CMAKE_SOURCE_DIR@/cmake/apple/dmg_branding.png", - "icon-size": 72, + "icon-size": 128, "contents": [ - { "x": 460, "y": 260, "type": "link", "path": "/Applications" }, - { "x": 220, "y": 260, "type": "file", "path": "@CMAKE_BINARY_DIR@/@MACOSX_BUNDLE_BUNDLE_NAME@.app" } + { "x": 139, "y": 200, "type": "file", "path": "@CMAKE_BINARY_DIR@/@MACOSX_BUNDLE_BUNDLE_NAME@.app" }, + { "x": 568, "y": 200, "type": "link", "path": "/Applications" } ] } diff --git a/cmake/apple/project.icns b/cmake/apple/project.icns index 930afc217..9ae58d7fb 100644 Binary files a/cmake/apple/project.icns and b/cmake/apple/project.icns differ diff --git a/cmake/build_win32.sh b/cmake/build_win32.sh index 6fbf5287b..33cd8ecce 100755 --- a/cmake/build_win32.sh +++ b/cmake/build_win32.sh @@ -37,4 +37,4 @@ fi CMAKE_OPTS="-DCMAKE_PREFIX_PATH=$MINGW $CMAKE_OPTS" # shellcheck disable=SC2086 -cmake "$DIR/.." -DCMAKE_TOOLCHAIN_FILE="$TOOLCHAIN" -DCMAKE_MODULE_PATH="$DIR/../cmake/modules/" $CMAKE_OPTS +cmake "$DIR/.." -DCMAKE_TOOLCHAIN_FILE="$TOOLCHAIN" $CMAKE_OPTS diff --git a/cmake/install/CMakeLists.txt b/cmake/install/CMakeLists.txt new file mode 100644 index 000000000..a3a81beeb --- /dev/null +++ b/cmake/install/CMakeLists.txt @@ -0,0 +1,41 @@ +SET(PLUGIN_FILES "") +IF(LMMS_BUILD_WIN32) + INSTALL(FILES $ DESTINATION platforms) +ENDIF() + +IF(LMMS_BUILD_WIN32 OR LMMS_INSTALL_DEPENDENCIES) + include(InstallTargetDependencies) + + # Collect directories to search for DLLs + GET_FILENAME_COMPONENT(QTBIN_DIR "${QT_QMAKE_EXECUTABLE}" PATH) + set(LIB_DIRS "${QTBIN_DIR}") + + GET_PROPERTY(PLUGINS_BUILT GLOBAL PROPERTY PLUGINS_BUILT) + + IF(LMMS_BUILD_WIN32) + SET(LMMS_DEP_DESTINATION ${BIN_DIR}) + SET(PLUGIN_DEP_DESTINATION ${BIN_DIR}) + ELSE() + SET(LMMS_DEP_DESTINATION ${LIB_DIR}) + SET(PLUGIN_DEP_DESTINATION ${LIB_DIR}) + ENDIF() + + INSTALL_TARGET_DEPENDENCIES( + NAME "main_binary" + TARGETS lmms + DESTINATION "${LMMS_DEP_DESTINATION}" + LIB_DIRS ${LIB_DIRS} + ) + + INSTALL_TARGET_DEPENDENCIES( + NAME "plugins" + TARGETS ${PLUGINS_BUILT} + DESTINATION ${PLUGIN_DEP_DESTINATION} + LIB_DIRS ${LIB_DIRS} "${PLUGIN_DIR}" + ) +ENDIF() + +IF(LMMS_BUILD_APPLE) + INSTALL(CODE "EXECUTE_PROCESS(COMMAND chmod u+x ${CMAKE_BINARY_DIR}/install_apple.sh)") + INSTALL(CODE "EXECUTE_PROCESS(COMMAND ${CMAKE_BINARY_DIR}/install_apple.sh)") +ENDIF() diff --git a/cmake/install/excludelist-win b/cmake/install/excludelist-win new file mode 100644 index 000000000..17793a113 --- /dev/null +++ b/cmake/install/excludelist-win @@ -0,0 +1,23 @@ +# List of DLLs considered to be system libraries. +# This is needed when cross-compiling for Windows. +ADVAPI32.dll +COMCTL32.dll +comdlg32.dll +dwmapi.dll +GDI32.dll +IMM32.dll +KERNEL32.dll +MPR.DLL +msvcrt.dll +ole32.dll +OLEAUT32.dll +OPENGL32.DLL +SHELL32.dll +USER32.dll +UxTheme.dll +VERSION.dll +WINMM.DLL +WS2_32.dll +RPCRT4.dll +dsound.dll +SETUPAPI.dll diff --git a/cmake/linux/CMakeLists.txt b/cmake/linux/CMakeLists.txt index 45f0e5e7a..27c6655eb 100644 --- a/cmake/linux/CMakeLists.txt +++ b/cmake/linux/CMakeLists.txt @@ -1,5 +1,4 @@ -INSTALL(FILES lmms.svg DESTINATION "${DATA_DIR}/icons/hicolor/scalable/apps") -INSTALL(FILES project.svg DESTINATION "${DATA_DIR}/icons/hicolor/scalable/mimetypes/" RENAME "application-x-lmms-project.svg") +INSTALL(DIRECTORY icons/ DESTINATION "${DATA_DIR}/icons/hicolor") INSTALL(FILES lmms.desktop DESTINATION "${DATA_DIR}/applications") INSTALL(FILES lmms.xml DESTINATION "${DATA_DIR}/mime/packages") diff --git a/cmake/linux/icons/128x128/apps/lmms.png b/cmake/linux/icons/128x128/apps/lmms.png new file mode 100644 index 000000000..7bad96f98 Binary files /dev/null and b/cmake/linux/icons/128x128/apps/lmms.png differ diff --git a/cmake/linux/icons/128x128/mimetypes/application-x-lmms-project.png b/cmake/linux/icons/128x128/mimetypes/application-x-lmms-project.png new file mode 100644 index 000000000..7a016d0ed Binary files /dev/null and b/cmake/linux/icons/128x128/mimetypes/application-x-lmms-project.png differ diff --git a/cmake/linux/icons/128x128@2/apps/lmms.png b/cmake/linux/icons/128x128@2/apps/lmms.png new file mode 100644 index 000000000..a75f1b237 Binary files /dev/null and b/cmake/linux/icons/128x128@2/apps/lmms.png differ diff --git a/cmake/linux/icons/128x128@2/mimetypes/application-x-lmms-project.png b/cmake/linux/icons/128x128@2/mimetypes/application-x-lmms-project.png new file mode 100644 index 000000000..e7dbe591f Binary files /dev/null and b/cmake/linux/icons/128x128@2/mimetypes/application-x-lmms-project.png differ diff --git a/cmake/linux/icons/16x16/apps/lmms.png b/cmake/linux/icons/16x16/apps/lmms.png new file mode 100644 index 000000000..7148c9373 Binary files /dev/null and b/cmake/linux/icons/16x16/apps/lmms.png differ diff --git a/cmake/linux/icons/16x16/mimetypes/application-x-lmms-project.png b/cmake/linux/icons/16x16/mimetypes/application-x-lmms-project.png new file mode 100644 index 000000000..b3ef2151e Binary files /dev/null and b/cmake/linux/icons/16x16/mimetypes/application-x-lmms-project.png differ diff --git a/cmake/linux/icons/16x16@2/apps/lmms.png b/cmake/linux/icons/16x16@2/apps/lmms.png new file mode 100644 index 000000000..f6ca1cb29 Binary files /dev/null and b/cmake/linux/icons/16x16@2/apps/lmms.png differ diff --git a/cmake/linux/icons/16x16@2/mimetypes/application-x-lmms-project.png b/cmake/linux/icons/16x16@2/mimetypes/application-x-lmms-project.png new file mode 100644 index 000000000..d4b20ae01 Binary files /dev/null and b/cmake/linux/icons/16x16@2/mimetypes/application-x-lmms-project.png differ diff --git a/cmake/linux/icons/24x24/apps/lmms.png b/cmake/linux/icons/24x24/apps/lmms.png new file mode 100644 index 000000000..988da8872 Binary files /dev/null and b/cmake/linux/icons/24x24/apps/lmms.png differ diff --git a/cmake/linux/icons/24x24/mimetypes/application-x-lmms-project.png b/cmake/linux/icons/24x24/mimetypes/application-x-lmms-project.png new file mode 100644 index 000000000..548660bb2 Binary files /dev/null and b/cmake/linux/icons/24x24/mimetypes/application-x-lmms-project.png differ diff --git a/cmake/linux/icons/24x24@2/apps/lmms.png b/cmake/linux/icons/24x24@2/apps/lmms.png new file mode 100644 index 000000000..76d9e5b9b Binary files /dev/null and b/cmake/linux/icons/24x24@2/apps/lmms.png differ diff --git a/cmake/linux/icons/24x24@2/mimetypes/application-x-lmms-project.png b/cmake/linux/icons/24x24@2/mimetypes/application-x-lmms-project.png new file mode 100644 index 000000000..a8bbf9d01 Binary files /dev/null and b/cmake/linux/icons/24x24@2/mimetypes/application-x-lmms-project.png differ diff --git a/cmake/linux/icons/32x32/apps/lmms.png b/cmake/linux/icons/32x32/apps/lmms.png new file mode 100644 index 000000000..5f67ceb1d Binary files /dev/null and b/cmake/linux/icons/32x32/apps/lmms.png differ diff --git a/cmake/linux/icons/32x32/mimetypes/application-x-lmms-project.png b/cmake/linux/icons/32x32/mimetypes/application-x-lmms-project.png new file mode 100644 index 000000000..9aabbde82 Binary files /dev/null and b/cmake/linux/icons/32x32/mimetypes/application-x-lmms-project.png differ diff --git a/cmake/linux/icons/32x32@2/apps/lmms.png b/cmake/linux/icons/32x32@2/apps/lmms.png new file mode 100644 index 000000000..4504c4a66 Binary files /dev/null and b/cmake/linux/icons/32x32@2/apps/lmms.png differ diff --git a/cmake/linux/icons/32x32@2/mimetypes/application-x-lmms-project.png b/cmake/linux/icons/32x32@2/mimetypes/application-x-lmms-project.png new file mode 100644 index 000000000..87ca938aa Binary files /dev/null and b/cmake/linux/icons/32x32@2/mimetypes/application-x-lmms-project.png differ diff --git a/cmake/linux/icons/48x48/apps/lmms.png b/cmake/linux/icons/48x48/apps/lmms.png new file mode 100644 index 000000000..4b2c9fc87 Binary files /dev/null and b/cmake/linux/icons/48x48/apps/lmms.png differ diff --git a/cmake/linux/icons/48x48/mimetypes/application-x-lmms-project.png b/cmake/linux/icons/48x48/mimetypes/application-x-lmms-project.png new file mode 100644 index 000000000..4ea287a9b Binary files /dev/null and b/cmake/linux/icons/48x48/mimetypes/application-x-lmms-project.png differ diff --git a/cmake/linux/icons/48x48@2/apps/lmms.png b/cmake/linux/icons/48x48@2/apps/lmms.png new file mode 100644 index 000000000..af2c5eda2 Binary files /dev/null and b/cmake/linux/icons/48x48@2/apps/lmms.png differ diff --git a/cmake/linux/icons/48x48@2/mimetypes/application-x-lmms-project.png b/cmake/linux/icons/48x48@2/mimetypes/application-x-lmms-project.png new file mode 100644 index 000000000..c583535d6 Binary files /dev/null and b/cmake/linux/icons/48x48@2/mimetypes/application-x-lmms-project.png differ diff --git a/cmake/linux/icons/64x64/apps/lmms.png b/cmake/linux/icons/64x64/apps/lmms.png new file mode 100644 index 000000000..52b25564f Binary files /dev/null and b/cmake/linux/icons/64x64/apps/lmms.png differ diff --git a/cmake/linux/icons/64x64/mimetypes/application-x-lmms-project.png b/cmake/linux/icons/64x64/mimetypes/application-x-lmms-project.png new file mode 100644 index 000000000..96bfae222 Binary files /dev/null and b/cmake/linux/icons/64x64/mimetypes/application-x-lmms-project.png differ diff --git a/cmake/linux/icons/64x64@2/apps/lmms.png b/cmake/linux/icons/64x64@2/apps/lmms.png new file mode 100644 index 000000000..9e9403a22 Binary files /dev/null and b/cmake/linux/icons/64x64@2/apps/lmms.png differ diff --git a/cmake/linux/icons/64x64@2/mimetypes/application-x-lmms-project.png b/cmake/linux/icons/64x64@2/mimetypes/application-x-lmms-project.png new file mode 100644 index 000000000..7a016d0ed Binary files /dev/null and b/cmake/linux/icons/64x64@2/mimetypes/application-x-lmms-project.png differ diff --git a/cmake/linux/icons/scalable/apps/lmms.svg b/cmake/linux/icons/scalable/apps/lmms.svg new file mode 100644 index 000000000..fc0867aa6 --- /dev/null +++ b/cmake/linux/icons/scalable/apps/lmms.svg @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/cmake/linux/icons/scalable/mimetypes/application-x-lmms-project.svg b/cmake/linux/icons/scalable/mimetypes/application-x-lmms-project.svg new file mode 100644 index 000000000..29697ece8 --- /dev/null +++ b/cmake/linux/icons/scalable/mimetypes/application-x-lmms-project.svg @@ -0,0 +1,173 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/cmake/linux/lmms.desktop b/cmake/linux/lmms.desktop index 0fb706a62..d6a05d15f 100644 --- a/cmake/linux/lmms.desktop +++ b/cmake/linux/lmms.desktop @@ -3,14 +3,14 @@ Name=LMMS GenericName=Music production suite GenericName[ca]=Programari de producció musical GenericName[de]=Software zur Musik-Produktion -GenericName[fr]=Ensemble pour la production musicale +GenericName[fr]=Suite de production musicale GenericName[pl]=Narzędzia do produkcji muzyki Comment=Music sequencer and synthesizer Comment[ca]=Producció fàcil de música per a tothom! -Comment[fr]=Production facile de musique pour tout le monde ! +Comment[fr]=Séquenceur et synthétiseur de musique Comment[pl]=Prosta produkcja muzyki dla każdego! Icon=lmms -Exec=env QT_X11_NO_NATIVE_MENUBAR=1 QT_AUTO_SCREEN_SCALE_FACTOR=1 lmms %f +Exec=lmms %f Terminal=false Type=Application Categories=Qt;AudioVideo;Audio;Midi; diff --git a/cmake/linux/lmms.png b/cmake/linux/lmms.png deleted file mode 100644 index ae9fe6a2a..000000000 Binary files a/cmake/linux/lmms.png and /dev/null differ diff --git a/cmake/linux/lmms.svg b/cmake/linux/lmms.svg deleted file mode 100644 index ffe6976ce..000000000 --- a/cmake/linux/lmms.svg +++ /dev/null @@ -1,1540 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cmake/linux/package_linux.sh.in b/cmake/linux/package_linux.sh.in index ec6224e35..9f233d401 100644 --- a/cmake/linux/package_linux.sh.in +++ b/cmake/linux/package_linux.sh.in @@ -57,6 +57,7 @@ PATH="$(pwd -P)/squashfs-root/usr/bin:$(dirname "@QT_QMAKE_EXECUTABLE@")":$PATH export PATH # Fetch portable linuxdeployqt if not in PATH +APPIMAGETOOL="squashfs-root/usr/bin/appimagetool" echo -e "\nDownloading linuxdeployqt to ${LINUXDEPLOYQT}..." if env -i which linuxdeployqt > /dev/null 2>&1; then skipped "System already provides this utility" @@ -73,9 +74,10 @@ else success "Downloaded $LINUXDEPLOYQT" # Extract AppImage and replace LINUXDEPLOYQT variable with extracted binary # to support systems without fuse + # Also, we need to set LD_LIBRARY_PATH, but linuxdepoyqt's AppRun unsets it + # See https://github.com/probonopd/linuxdeployqt/pull/370/ "$LINUXDEPLOYQT" --appimage-extract > /dev/null 2>&1 - LINUXDEPLOYQT="squashfs-root/AppRun" - APPIMAGETOOL="squashfs-root/usr/bin/appimagetool" + LINUXDEPLOYQT="squashfs-root/usr/bin/linuxdeployqt" success "Extracted $APPIMAGETOOL" fi @@ -101,8 +103,9 @@ mv "${APPDIR}usr/bin/lmms" "${APPDIR}usr/bin/lmms.real" cat >"${APPDIR}usr/bin/lmms" < /dev/null 2>&1; then - CARLAPATH="$(which carla)" + CARLAPATH="\$(which carla)" CARLAPREFIX="\${CARLAPATH%/bin*}" echo "Carla appears to be installed on this system at \$CARLAPREFIX/lib[64]/carla so we'll use it." export LD_LIBRARY_PATH=\$CARLAPREFIX/lib/carla:\$CARLAPREFIX/lib64/carla:\$LD_LIBRARY_PATH @@ -126,26 +129,32 @@ EOL chmod +x "${APPDIR}usr/bin/lmms" -# Per https://github.com/probonopd/linuxdeployqt/issues/129 +# Per https://github.com/probonopd/linuxdeployqt/issues/129 unset LD_LIBRARY_PATH # Ensure linuxdeployqt can find shared objects export LD_LIBRARY_PATH="${APPDIR}usr/lib/lmms/":$LD_LIBRARY_PATH # Handle wine linking -if [ -d "@WINE_LIBRARY_FIX@" ]; then - export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:@WINE_LIBRARY_FIX@:@WINE_LIBRARY_FIX@wine/ +if [ -d "@WINE_32_LIBRARY_DIR@" ]; then + export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:@WINE_32_LIBRARY_DIRS@ +fi +if [ -d "@WINE_64_LIBRARY_DIR@" ]; then + export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:@WINE_64_LIBRARY_DIRS@ fi # Move executables so linuxdeployqt can find them ZYNLIB="${APPDIR}usr/lib/lmms/RemoteZynAddSubFx" -VSTLIB="${APPDIR}usr/lib/lmms/RemoteVstPlugin.exe.so" +VSTLIB32="${APPDIR}usr/lib/lmms/32/RemoteVstPlugin32.exe.so" +VSTLIB64="${APPDIR}usr/lib/lmms/RemoteVstPlugin64.exe.so" ZYNBIN="${APPDIR}usr/bin/RemoteZynAddSubFx" -VSTBIN="${APPDIR}usr/bin/RemoteVstPlugin.exe.so" +VSTBIN32="${APPDIR}usr/bin/RemoteVstPlugin32.exe.so" +VSTBIN64="${APPDIR}usr/bin/RemoteVstPlugin64.exe.so" mv "$ZYNLIB" "$ZYNBIN" -mv "$VSTLIB" "$VSTBIN" +mv "$VSTLIB32" "$VSTBIN32" +mv "$VSTLIB64" "$VSTBIN64" # Patch the desktop file sed -i 's/.*Exec=.*/Exec=lmms.real/' "$DESKTOPFILE" @@ -156,7 +165,8 @@ for file in "${APPDIR}usr/lib/lmms/"*.so; do executables="${executables} -executable=$thisfile" done executables="${executables} -executable=${ZYNBIN}" -executables="${executables} -executable=${VSTBIN}" +executables="${executables} -executable=${VSTBIN32}" +executables="${executables} -executable=${VSTBIN64}" executables="${executables} -executable=${APPDIR}usr/lib/lmms/ladspa/imp_1199.so" executables="${executables} -executable=${APPDIR}usr/lib/lmms/ladspa/imbeq_1197.so" executables="${executables} -executable=${APPDIR}usr/lib/lmms/ladspa/pitch_scale_1193.so" @@ -165,13 +175,15 @@ 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" + # shellcheck disable=SC2086 "$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 ln -sr "$ZYNBIN" "$ZYNLIB" -ln -sr "$VSTBIN" "$VSTLIB" +ln -sr "$VSTBIN32" "$VSTLIB32" +ln -sr "$VSTBIN64" "$VSTLIB64" # Remove wine library conflict rm -f "${APPDIR}/usr/lib/libwine.so.1" @@ -179,12 +191,22 @@ rm -f "${APPDIR}/usr/lib/libwine.so.1" # Use system-provided carla rm -f "${APPDIR}usr/lib/"libcarla*.so -# Move jack out of LD_LIBRARY_PATH +# Remove bundled jack in LD_LIBRARY_PATH if exists if [ -e "${APPDIR}/usr/lib/libjack.so.0" ]; then - mkdir -p "${APPDIR}usr/lib/lmms/optional/" - mv "${APPDIR}/usr/lib/libjack.so.0" "${APPDIR}usr/lib/lmms/optional/" + rm "${APPDIR}/usr/lib/libjack.so.0" fi +# Bundle jack out of LD_LIBRARY_PATH +JACK_LIB=$(ldd "${APPDIR}/usr/bin/lmms.real" | sed -n 's/\tlibjack\.so\.0 => \(.\+\) (0x[0-9a-f]\+)/\1/p') +if [ -e "$JACK_LIB" ]; then + mkdir -p "${APPDIR}usr/lib/lmms/optional/" + cp "$JACK_LIB" "${APPDIR}usr/lib/lmms/optional/" +fi + +# Point the AppRun to the shim launcher +rm -f "${APPDIR}/AppRun" +ln -sr "${APPDIR}/usr/bin/lmms" "${APPDIR}/AppRun" + # Create AppImage echo -e "\nFinishing the AppImage..." echo -e "\n\n>>>>> appimagetool" >> "$LOGFILE" diff --git a/cmake/linux/project.svg b/cmake/linux/project.svg deleted file mode 100644 index 62888e277..000000000 --- a/cmake/linux/project.svg +++ /dev/null @@ -1,1912 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mmpz - - - - mmpz - mmpz - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cmake/modules/BashCompletion.cmake b/cmake/modules/BashCompletion.cmake new file mode 100644 index 000000000..c3916f201 --- /dev/null +++ b/cmake/modules/BashCompletion.cmake @@ -0,0 +1,93 @@ +# A wrapper around pkg-config-provided and cmake-provided bash completion that +# will have dynamic behavior at INSTALL() time to allow both root-level +# INSTALL() as well as user-level INSTALL(). +# +# See also https://github.com/scop/bash-completion +# +# Copyright (c) 2018, Tres Finocchiaro, +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. +# +# Usage: +# INCLUDE(BashCompletion) +# BASHCOMP_INSTALL(foo) +# ... where "foo" is a shell script adjacent to the CMakeLists.txt +# +# How it determines BASHCOMP_PKG_PATH, in order: +# 1. Uses BASHCOMP_PKG_PATH if already set (e.g. -DBASHCOMP_PKG_PATH=...) +# a. If not, uses pkg-config's PKG_CHECK_MODULES to determine path +# b. Fallback to cmake's FIND_PACKAGE(bash-completion) path +# c. Fallback to hard-coded /usr/share/bash-completion/completions +# 2. Final fallback to ${CMAKE_INSTALL_PREFIX}/share/bash-completion/completions if +# detected path is unwritable. + +# - Windows does not support bash completion +# - macOS support should eventually be added for Homebrew (TODO) +IF(WIN32) + MESSAGE(STATUS "Bash competion is not supported on this platform.") +ELSEIF(APPLE) + MESSAGE(STATUS "Bash completion is not yet implemented for this platform.") +ELSE() + INCLUDE(FindUnixCommands) + # Honor manual override if provided + IF(NOT BASHCOMP_PKG_PATH) + # First, use pkg-config, which is the most reliable + FIND_PACKAGE(PkgConfig QUIET) + IF(PKGCONFIG_FOUND) + PKG_CHECK_MODULES(BASH_COMPLETION bash-completion) + PKG_GET_VARIABLE(BASHCOMP_PKG_PATH bash-completion completionsdir) + ELSE() + # Second, use cmake (preferred but less common) + FIND_PACKAGE(bash-completion QUIET) + IF(BASH_COMPLETION_FOUND) + SET(BASHCOMP_PKG_PATH "${BASH_COMPLETION_COMPLETIONSDIR}") + ENDIF() + ENDIF() + + # Third, use a hard-coded fallback value + IF("${BASHCOMP_PKG_PATH}" STREQUAL "") + SET(BASHCOMP_PKG_PATH "/usr/share/bash-completion/completions") + ENDIF() + ENDIF() + + # Always provide a fallback for non-root INSTALL() + SET(BASHCOMP_USER_PATH "${CMAKE_INSTALL_PREFIX}/share/bash-completion/completions") + + # Cmake doesn't allow easy use of conditional logic at INSTALL() time + # this is a problem because ${BASHCOMP_PKG_PATH} may not be writable and we + # need sane fallback behavior for bundled INSTALL() (e.g. .AppImage, etc). + # + # The reason this can't be detected by cmake is that it's fairly common to + # run "cmake" as a one user (i.e. non-root) and "make install" as another user + # (i.e. root). + # + # - Creates a script called "install_${SCRIPT_NAME}_completion.sh" into the + # working binary directory and invokes this script at install. + # - Script handles INSTALL()-time conditional logic for sane ballback behavior + # when ${BASHCOMP_PKG_PATH} is unwritable (i.e. non-root); Something cmake + # can't handle on its own at INSTALL() time) + MACRO(BASHCOMP_INSTALL SCRIPT_NAME) + # A shell script for wrapping conditionl logic + SET(BASHCOMP_SCRIPT "${CMAKE_CURRENT_BINARY_DIR}/install_${SCRIPT_NAME}_completion.sh") + + FILE(WRITE ${BASHCOMP_SCRIPT} "\ +#!${BASH}\n\ +set -e\n\ +if [ -w \"${BASHCOMP_PKG_PATH}\" ]; then\n\ + BASHCOMP_PKG_PATH=\"${BASHCOMP_PKG_PATH}\"\n\ +else \n\ + BASHCOMP_PKG_PATH=\"\$DESTDIR${BASHCOMP_USER_PATH}\"\n\ +fi\n\ +echo -e \"\\nInstalling bash completion...\\n\"\n\ +mkdir -p \"\$BASHCOMP_PKG_PATH\"\n\ +cp \"${CMAKE_CURRENT_SOURCE_DIR}/${SCRIPT_NAME}\" \"\$BASHCOMP_PKG_PATH\"\n\ +chmod a+r \"\$BASHCOMP_PKG_PATH/${SCRIPT_NAME}\"\n\ +echo -e \"Bash completion for ${SCRIPT_NAME} has been installed to \$BASHCOMP_PKG_PATH/${SCRIPT_NAME}\"\n\ +") + INSTALL(CODE "EXECUTE_PROCESS(COMMAND chmod u+x \"install_${SCRIPT_NAME}_completion.sh\" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} )") + INSTALL(CODE "EXECUTE_PROCESS(COMMAND \"./install_${SCRIPT_NAME}_completion.sh\" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} )") + + MESSAGE(STATUS "Bash completion script for ${SCRIPT_NAME} will be installed to ${BASHCOMP_PKG_PATH} or fallback to ${BASHCOMP_USER_PATH} if unwritable.") + ENDMACRO() +ENDIF() + diff --git a/cmake/modules/BuildPlugin.cmake b/cmake/modules/BuildPlugin.cmake index 1722e3dce..675433e63 100644 --- a/cmake/modules/BuildPlugin.cmake +++ b/cmake/modules/BuildPlugin.cmake @@ -6,10 +6,10 @@ INCLUDE(GenQrc) MACRO(BUILD_PLUGIN PLUGIN_NAME) - CMAKE_PARSE_ARGUMENTS(PLUGIN "" "" "MOCFILES;EMBEDDED_RESOURCES;UICFILES;LINK" ${ARGN}) + CMAKE_PARSE_ARGUMENTS(PLUGIN "" "LINK;EXPORT_BASE_NAME" "MOCFILES;EMBEDDED_RESOURCES;UICFILES" ${ARGN}) SET(PLUGIN_SOURCES ${PLUGIN_UNPARSED_ARGUMENTS}) - INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/include) + INCLUDE_DIRECTORIES("${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_BINARY_DIR}" "${CMAKE_SOURCE_DIR}/include") ADD_DEFINITIONS(-DPLUGIN_NAME=${PLUGIN_NAME}) @@ -22,7 +22,7 @@ MACRO(BUILD_PLUGIN PLUGIN_NAME) FILE(GLOB EXPANDED "${ARG}") LIST(SORT EXPANDED) FOREACH(ITEM ${EXPANDED}) - LIST(APPEND NEW_ARGS ${ITEM}) + LIST(APPEND NEW_ARGS "${ITEM}") ENDFOREACH() ENDFOREACH() SET(PLUGIN_EMBEDDED_RESOURCES ${NEW_ARGS}) @@ -38,11 +38,11 @@ MACRO(BUILD_PLUGIN PLUGIN_NAME) ENDFOREACH(f) IF(LMMS_BUILD_APPLE) - LINK_DIRECTORIES(${CMAKE_BINARY_DIR}) + LINK_DIRECTORIES("${CMAKE_BINARY_DIR}") LINK_LIBRARIES(${QT_LIBRARIES}) ENDIF(LMMS_BUILD_APPLE) IF(LMMS_BUILD_WIN32) - LINK_DIRECTORIES(${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}) + LINK_DIRECTORIES("${CMAKE_BINARY_DIR}" "${CMAKE_SOURCE_DIR}") LINK_LIBRARIES(${QT_LIBRARIES}) ENDIF(LMMS_BUILD_WIN32) IF(LMMS_BUILD_MSYS AND CMAKE_BUILD_TYPE STREQUAL "Debug") @@ -50,11 +50,11 @@ MACRO(BUILD_PLUGIN PLUGIN_NAME) SET(QT_LIBRARIES "${QT_OVERRIDE_LIBRARIES}") ENDIF() - IF ("${PLUGIN_LINK}" STREQUAL "SHARED") - ADD_LIBRARY(${PLUGIN_NAME} SHARED ${PLUGIN_SOURCES} ${plugin_MOC_out} ${RCC_OUT}) - ELSE () - ADD_LIBRARY(${PLUGIN_NAME} MODULE ${PLUGIN_SOURCES} ${plugin_MOC_out} ${RCC_OUT}) - ENDIF () + IF (NOT PLUGIN_LINK) + SET(PLUGIN_LINK "MODULE") + ENDIF() + + ADD_LIBRARY(${PLUGIN_NAME} ${PLUGIN_LINK} ${PLUGIN_SOURCES} ${plugin_MOC_out} ${RCC_OUT}) TARGET_LINK_LIBRARIES(${PLUGIN_NAME} Qt5::Widgets Qt5::Xml) @@ -62,17 +62,40 @@ MACRO(BUILD_PLUGIN PLUGIN_NAME) TARGET_LINK_LIBRARIES(${PLUGIN_NAME} lmms) ENDIF(LMMS_BUILD_WIN32) - INSTALL(TARGETS ${PLUGIN_NAME} LIBRARY DESTINATION "${PLUGIN_DIR}") + INSTALL(TARGETS ${PLUGIN_NAME} + LIBRARY DESTINATION "${PLUGIN_DIR}" + RUNTIME DESTINATION "${PLUGIN_DIR}" + ) IF(LMMS_BUILD_APPLE) - SET_TARGET_PROPERTIES(${PLUGIN_NAME} PROPERTIES LINK_FLAGS "-bundle_loader ${CMAKE_BINARY_DIR}/lmms") + IF ("${PLUGIN_LINK}" STREQUAL "SHARED") + SET_TARGET_PROPERTIES(${PLUGIN_NAME} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup") + ELSE() + SET_TARGET_PROPERTIES(${PLUGIN_NAME} PROPERTIES LINK_FLAGS "-bundle_loader \"${CMAKE_BINARY_DIR}/lmms\"") + 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}") + + IF(NOT PLUGIN_EXPORT_BASE_NAME) + SET(PLUGIN_EXPORT_BASE_NAME "PLUGIN") + ENDIF() + + GENERATE_EXPORT_HEADER(${PLUGIN_NAME} + BASE_NAME ${PLUGIN_EXPORT_BASE_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/CheckCXXPreprocessor.cmake b/cmake/modules/CheckCXXPreprocessor.cmake new file mode 100644 index 000000000..f841f52d1 --- /dev/null +++ b/cmake/modules/CheckCXXPreprocessor.cmake @@ -0,0 +1,33 @@ + +macro(CHECK_CXX_PREPROCESSOR VAR DIRECTIVE) + string(RANDOM DEFINED_KEY) + string(RANDOM UNDEFINED_KEY) + + set(TMP_FILENAME "${CMAKE_CURRENT_BINARY_DIR}/CxxTmp/src.cpp") + SET(SRC " + #if ${DIRECTIVE} + #error ${DEFINED_KEY} + #else + #error ${UNDEFINED_KEY} + #endif + ") + file(WRITE ${TMP_FILENAME} "${SRC}") + try_compile(RESULT_VAR + ${CMAKE_CURRENT_BINARY_DIR} + ${TMP_FILENAME} + OUTPUT_VARIABLE OUTPUT_VAR + ) + + if(OUTPUT_VAR MATCHES ${DEFINED_KEY}) + set(${VAR} ON) + elseif(OUTPUT_VAR MATCHES ${UNDEFINED_KEY}) + set(${VAR} OFF) + else() + message(FATAL_ERROR "Can't determine if \"${DIRECTIVE}\" is true.") + endif() +endmacro() + + +macro(CHECK_CXX_DEFINE VAR DEFINE) + CHECK_CXX_PREPROCESSOR(${VAR} "defined(${DEFINE})") +endmacro() diff --git a/cmake/modules/CheckSubmodules.cmake b/cmake/modules/CheckSubmodules.cmake index 55c0381b8..32a2f9951 100644 --- a/cmake/modules/CheckSubmodules.cmake +++ b/cmake/modules/CheckSubmodules.cmake @@ -7,18 +7,20 @@ # 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. # Files which confirm a successful clone -SET(VALID_CRUMBS "CMakeLists.txt;Makefile;Makefile.in;Makefile.am;configure.ac;configure.py;autogen.sh;.gitignore") +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) @@ -26,7 +28,13 @@ 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!" + ) + RETURN() +ENDIF() FILE(READ "${CMAKE_SOURCE_DIR}/.gitmodules" SUBMODULE_DATA) # Force English locale @@ -35,74 +43,112 @@ SET(LANG_BACKUP "$ENV{LANG}") SET(ENV{LC_ALL} "C") SET(ENV{LANG} "en_US") -# Assume alpha-numeric paths -STRING(REGEX MATCHALL "path = [-0-9A-Za-z/]+" SUBMODULE_LIST ${SUBMODULE_DATA}) -STRING(REGEX MATCHALL "url = [.:%-0-9A-Za-z/]+" SUBMODULE_URL_LIST ${SUBMODULE_DATA}) +# Submodule list pairs, unparsed (WARNING: Assumes alpha-numeric paths) +STRING(REGEX MATCHALL "path = [-0-9A-Za-z/]+" SUBMODULE_LIST_RAW ${SUBMODULE_DATA}) +STRING(REGEX MATCHALL "url = [.:%-0-9A-Za-z/]+" SUBMODULE_URL_RAW ${SUBMODULE_DATA}) -FOREACH(_part ${SUBMODULE_LIST}) - STRING(REPLACE "path = " "" SUBMODULE_PATH ${_part}) +# Submodule list pairs, parsed +SET(SUBMODULE_LIST "") +SET(SUBMODULE_URL "") - LIST(FIND SUBMODULE_LIST ${_part} SUBMODULE_INDEX) - LIST(GET SUBMODULE_URL_LIST ${SUBMODULE_INDEX} _url) - STRING(REPLACE "url = " "" SUBMODULE_URL ${_url}) +FOREACH(_path ${SUBMODULE_LIST_RAW}) + # Parse SUBMODULE_PATH + STRING(REPLACE "path = " "" SUBMODULE_PATH "${_path}") + + # Grab index for matching SUBMODULE_URL + LIST(FIND SUBMODULE_LIST_RAW "${_path}" SUBMODULE_INDEX) + LIST(GET SUBMODULE_URL_RAW ${SUBMODULE_INDEX} _url) + + # Parse SUBMODULE_URL + STRING(REPLACE "url = " "" SUBMODULE_URL "${_url}") - # Remove submodules from validation as specified in -DSKIP_SUBMODULES=foo;bar SET(SKIP false) + + # Loop over skipped plugins, add to SKIP_SUBMODULES (e.g. -DPLUGIN_LIST=foo;bar) + IF(${SUBMODULE_PATH} MATCHES "^plugins/") + SET(REMOVE_PLUGIN true) + FOREACH(_plugin ${PLUGIN_LIST}) + IF(_plugin STREQUAL "") + CONTINUE() + ENDIF() + IF(${SUBMODULE_PATH} MATCHES "${_plugin}") + SET(REMOVE_PLUGIN false) + ENDIF() + ENDFOREACH() + + IF(REMOVE_PLUGIN) + LIST(APPEND SKIP_SUBMODULES "${SUBMODULE_PATH}") + ENDIF() + ENDIF() + + # Finally, loop and mark "SKIP" on match IF(SKIP_SUBMODULES) FOREACH(_skip ${SKIP_SUBMODULES}) - IF(${SUBMODULE_PATH} MATCHES ${_skip}) - MESSAGE("-- Skipping ${SUBMODULE_PATH} matches \"${_skip}\"") + IF("${SUBMODULE_PATH}" MATCHES "${_skip}") + MESSAGE("-- Skipping ${SUBMODULE_PATH} matches \"${_skip}\" (absent in PLUGIN_LIST)") SET(SKIP true) + BREAK() ENDIF() ENDFOREACH() ENDIF() - IF(NOT SKIP) - LIST(INSERT SUBMODULE_LIST ${SUBMODULE_INDEX} ${SUBMODULE_PATH}) - LIST(INSERT SUBMODULE_URL_LIST ${SUBMODULE_INDEX} ${SUBMODULE_URL}) - ENDIF() - LIST(REMOVE_ITEM SUBMODULE_LIST ${_part}) - LIST(REMOVE_ITEM SUBMODULE_URL_LIST ${_url}) -ENDFOREACH() + IF(NOT SKIP) + LIST(APPEND SUBMODULE_LIST "${SUBMODULE_PATH}") + LIST(APPEND SUBMODULE_URL "${SUBMODULE_URL}") + ENDIF() +ENDFOREACH() # Once called, status is stored in GIT_RESULT respectively. # Note: Git likes to write to stderr. Don't assume stderr is error; Check GIT_RESULT instead. -MACRO(GIT_SUBMODULE SUBMODULE_PATH FORCE_DEINIT FORCE_REMOTE) +MACRO(GIT_SUBMODULE SUBMODULE_PATH FORCE_DEINIT FORCE_REMOTE FULL_CLONE) FIND_PACKAGE(Git REQUIRED) # Handle missing commits SET(FORCE_REMOTE_FLAG "${FORCE_REMOTE}") + SET(FULL_CLONE_FLAG "${FULL_CLONE}") IF(FORCE_REMOTE_FLAG) MESSAGE("-- Adding remote submodulefix to ${SUBMODULE_PATH}") EXECUTE_PROCESS( - COMMAND ${GIT_EXECUTABLE} remote rm submodulefix - COMMAND ${GIT_EXECUTABLE} remote add submodulefix ${FORCE_REMOTE} - COMMAND ${GIT_EXECUTABLE} fetch submodulefix - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/${SUBMODULE_PATH} + COMMAND "${GIT_EXECUTABLE}" remote rm submodulefix + COMMAND "${GIT_EXECUTABLE}" remote add submodulefix ${FORCE_REMOTE} + COMMAND "${GIT_EXECUTABLE}" fetch submodulefix + WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/${SUBMODULE_PATH}" OUTPUT_QUIET ERROR_QUIET ) # Recurse - GIT_SUBMODULE(${SUBMODULE_PATH} false false) + GIT_SUBMODULE(${SUBMODULE_PATH} false false ${FULL_CLONE_FLAG}) ELSEIF(${FORCE_DEINIT}) MESSAGE("-- Resetting ${SUBMODULE_PATH}") EXECUTE_PROCESS( - COMMAND ${GIT_EXECUTABLE} submodule deinit -f ${CMAKE_SOURCE_DIR}/${SUBMODULE_PATH} - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + COMMAND "${GIT_EXECUTABLE}" submodule deinit -f "${CMAKE_SOURCE_DIR}/${SUBMODULE_PATH}" + WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" OUTPUT_QUIET ) + MESSAGE("-- Deleting ${CMAKE_SOURCE_DIR}/.git/${SUBMODULE_PATH}") + FILE(REMOVE_RECURSE "${CMAKE_SOURCE_DIR}/.git/modules/${SUBMODULE_PATH}") # Recurse - GIT_SUBMODULE(${SUBMODULE_PATH} false false) + GIT_SUBMODULE(${SUBMODULE_PATH} false false true) ELSE() # Try to use the depth switch - SET(DEPTH_CMD "") + IF(NO_SHALLOW_CLONE OR GIT_VERSION_STRING VERSION_LESS "1.8.4") + # Shallow submodules were introduced in 1.8.4 MESSAGE("-- Fetching ${SUBMODULE_PATH}") - IF(DEPTH_VALUE) - SET(DEPTH_CMD "--depth" ) + SET(DEPTH_CMD "") + SET(DEPTH_VAL "") + ELSEIF(FULL_CLONE_FLAG) + # Depth doesn't revert easily... It should be "--no-recommend-shallow" + # but it's ignored by nested submodules, use the highest value instead. + MESSAGE("-- Fetching ${SUBMODULE_PATH}") + SET(DEPTH_CMD "--depth") + SET(DEPTH_VAL "2147483647") + ELSE() MESSAGE("-- Fetching ${SUBMODULE_PATH} @ --depth ${DEPTH_VALUE}") + SET(DEPTH_CMD "--depth") + SET(DEPTH_VAL "${DEPTH_VALUE}") ENDIF() EXECUTE_PROCESS( - COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive ${DEPTH_CMD} ${DEPTH_VALUE} ${CMAKE_SOURCE_DIR}/${SUBMODULE_PATH} - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + COMMAND "${GIT_EXECUTABLE}" submodule update --init --recursive ${DEPTH_CMD} ${DEPTH_VAL} "${CMAKE_SOURCE_DIR}/${SUBMODULE_PATH}" + WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" RESULT_VARIABLE GIT_RESULT OUTPUT_VARIABLE GIT_STDOUT ERROR_VARIABLE GIT_STDERR @@ -118,7 +164,7 @@ SET(RETRY_PHRASES "Failed to recurse;cannot create directory;already exists;${MI # Attempt to do lazy clone FOREACH(_submodule ${SUBMODULE_LIST}) - STRING(REPLACE "/" ";" PATH_PARTS ${_submodule}) + STRING(REPLACE "/" ";" PATH_PARTS "${_submodule}") LIST(REVERSE PATH_PARTS) LIST(GET PATH_PARTS 0 SUBMODULE_NAME) @@ -132,14 +178,12 @@ FOREACH(_submodule ${SUBMODULE_LIST}) ENDIF() ENDFOREACH() IF(NOT CRUMB_FOUND) - GIT_SUBMODULE(${_submodule} false false) + GIT_SUBMODULE("${_submodule}" false false false) SET(COUNTED 0) - SET(COUNTING "") # Handle edge-cases where submodule didn't clone properly or re-uses a non-empty directory WHILE(NOT GIT_RESULT EQUAL 0 AND COUNTED LESS MAX_ATTEMPTS) - LIST(APPEND COUNTING "x") - LIST(LENGTH COUNTING COUNTED) + MATH(EXPR COUNTED "${COUNTED}+1") SET(MISSING_COMMIT false) FOREACH(_phrase ${MISSING_COMMIT_PHRASES}) IF("${GIT_MESSAGE}" MATCHES "${_phrase}") @@ -148,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/CheckWineGcc.cmake b/cmake/modules/CheckWineGcc.cmake new file mode 100644 index 000000000..2956198d8 --- /dev/null +++ b/cmake/modules/CheckWineGcc.cmake @@ -0,0 +1,27 @@ +INCLUDE(CheckCXXSourceCompiles) + +FUNCTION(CheckWineGcc BITNESS WINEGCC_EXECUTABLE RESULT) + FILE(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/winegcc_test.cxx" " + #include + #define USE_WS_PREFIX + #include + int main(int argc, const char* argv[]) { + return 0; + } + ") + EXECUTE_PROCESS(COMMAND ${WINEGCC_EXECUTABLE} "-m${BITNESS}" + "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/winegcc_test.cxx" + "-o" "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/winegcc_test" + OUTPUT_QUIET ERROR_QUIET + RESULT_VARIABLE WINEGCC_RESULT + ) + FILE(REMOVE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/winegcc_test.cxx" + "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/winegcc_test" + "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/winegcc_test.exe.so" + ) + IF(WINEGCC_RESULT EQUAL 0) + SET(${RESULT} True PARENT_SCOPE) + ELSE() + SET(${RESULT} False PARENT_SCOPE) + ENDIF() +ENDFUNCTION() diff --git a/cmake/modules/CompileCache.cmake b/cmake/modules/CompileCache.cmake new file mode 100644 index 000000000..ed4622bd9 --- /dev/null +++ b/cmake/modules/CompileCache.cmake @@ -0,0 +1,25 @@ +option(USE_COMPILE_CACHE "Use ccache or clcache for compilation" OFF) + +# Compatibility for old option name +if(USE_CCACHE) + set(USE_COMPILE_CACHE ON) +endif() + +if(USE_COMPILE_CACHE) + if(MSVC) + set(CACHE_TOOL_NAME clcache) + elseif(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|AppleClang|Clang)") + set(CACHE_TOOL_NAME ccache) + else() + message(WARNING "Compile cache only available with MSVC or GNU") + endif() + + find_program(CACHE_TOOL ${CACHE_TOOL_NAME}) + if (CACHE_TOOL) + message(STATUS "Using ${CACHE_TOOL} found for caching") + set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CACHE_TOOL}) + set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ${CACHE_TOOL}) + else() + message(WARNING "USE_COMPILE_CACHE enabled, but no ${CACHE_TOOL_NAME} found") + endif() +endif() diff --git a/cmake/modules/CreateTempFile.cmake b/cmake/modules/CreateTempFile.cmake new file mode 100644 index 000000000..5210342ac --- /dev/null +++ b/cmake/modules/CreateTempFile.cmake @@ -0,0 +1,21 @@ +function(CreateTempFilePath) + set(options CONFIG_SUFFIX) + set(oneValueArgs OUTPUT_VAR TAG) + set(multiValueArgs CONTENT) + cmake_parse_arguments(TEMP "${options}" "${oneValueArgs}" + "${multiValueArgs}" ${ARGN} ) + + # Use hash to create a unique identifier + # for this file. + string(SHA1 hashed_content "${TEMP_CONTENT}") + + set(file_name "${CMAKE_BINARY_DIR}/${TEMP_TAG}_${hashed_content}") + set(${TEMP_OUTPUT_VAR} "${file_name}" PARENT_SCOPE) + if(CONFIG_SUFFIX) + set(file_name "${file_name}_$") + endif() + + file(GENERATE OUTPUT "${file_name}" + CONTENT "${TEMP_CONTENT}") + +endfunction() diff --git a/cmake/modules/DefineInstallVar.cmake b/cmake/modules/DefineInstallVar.cmake new file mode 100644 index 000000000..b13cb1d52 --- /dev/null +++ b/cmake/modules/DefineInstallVar.cmake @@ -0,0 +1,31 @@ +# This functions forwards a variable to +# the install stage. +# Parameters: +# CONTENT: Variable content. +# NAME: Variable name. +# Options: +# GENERATOR_EXPRESSION: Support generator expression for CONTENT. +function(DEFINE_INSTALL_VAR) + set(options GENERATOR_EXPRESSION) + set(oneValueArgs NAME ) + set(multiValueArgs CONTENT) + cmake_parse_arguments(VAR "${options}" "${oneValueArgs}" + "${multiValueArgs}" ${ARGN} ) + + # install(CODE) does not support generator expression in ver<3.14 + if(VAR_GENERATOR_EXPRESSION AND ${CMAKE_VERSION} VERSION_LESS "3.14.0") + include(CreateTempFile) + if(CMAKE_CONFIGURATION_TYPES) # in case of multi-config generators like MSVC generators + CreateTempFilePath(OUTPUT_VAR file_path TAG "${VAR_NAME}" CONTENT "${VAR_CONTENT}" CONFIG_SUFFIX) + install(CODE "file(READ \"${file_path}_\${CMAKE_INSTALL_CONFIG_NAME}\" \"${VAR_NAME}\")") + else() + CreateTempFilePath(OUTPUT_VAR file_path TAG "${VAR_NAME}" CONTENT "${VAR_CONTENT}") + install(CODE "file(READ \"${file_path}\" \"${VAR_NAME}\")") + endif() + else() + if(VAR_GENERATOR_EXPRESSION) + cmake_policy(SET CMP0087 NEW) + endif() + install(CODE "set(\"${VAR_NAME}\" \"${VAR_CONTENT}\")") + endif() +endfunction() diff --git a/cmake/modules/DetectMachine.cmake b/cmake/modules/DetectMachine.cmake index 14efad76a..86807b757 100644 --- a/cmake/modules/DetectMachine.cmake +++ b/cmake/modules/DetectMachine.cmake @@ -4,20 +4,25 @@ 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() SET(LMMS_BUILD_LINUX 1) ENDIF(WIN32) -# See build_winXX.sh for LMMS_BUILD_MSYS +# LMMS_BUILD_MSYS also set in build_winXX.sh +IF(LMMS_BUILD_WIN32 AND CMAKE_COMPILER_IS_GNUCXX AND DEFINED ENV{MSYSCON}) + SET(LMMS_BUILD_MSYS TRUE) +ENDIF() MESSAGE("PROCESSOR: ${CMAKE_SYSTEM_PROCESSOR}") SET(LMMS_HOST_X86 FALSE) SET(LMMS_HOST_X86_64 FALSE) -IF(MSVC) - STRING(REGEX MATCH "86_64|amd64|AMD64" WIN64 "${CMAKE_SYSTEM_PROCESSOR}") +IF(NOT DEFINED WIN64 AND CMAKE_SIZEOF_VOID_P EQUAL 8) + SET(WIN64 ON) ENDIF() IF(WIN32) @@ -27,6 +32,25 @@ IF(WIN32) ELSE(WIN64) SET(IS_X86 TRUE) ENDIF(WIN64) + + if(MSVC) + SET(MSVC_VER ${CMAKE_CXX_COMPILER_VERSION}) + + IF(MSVC_VER VERSION_GREATER 19.20 OR MSVC_VER VERSION_EQUAL 19.20) + SET(LMMS_MSVC_GENERATOR "Visual Studio 16 2019") + SET(LMMS_MSVC_YEAR 2019) # Qt only provides binaries for MSVC 2017, but 2019 is binary compatible + ELSEIF(MSVC_VER VERSION_GREATER 19.10 OR MSVC_VER VERSION_EQUAL 19.10) + SET(LMMS_MSVC_GENERATOR "Visual Studio 15 2017") + SET(LMMS_MSVC_YEAR 2017) + ELSEIF(MSVC_VER VERSION_GREATER 19.0 OR MSVC_VER VERSION_EQUAL 19.0) + SET(LMMS_MSVC_GENERATOR "Visual Studio 14 2015") + SET(LMMS_MSVC_YEAR 2015) + ELSE() + MESSAGE(SEND_WARNING "Can't detect MSVC version: ${MSVC_VER}") + ENDIF() + + unset(MSVC_VER) + endif() ELSE(WIN32) EXEC_PROGRAM( ${CMAKE_C_COMPILER} ARGS "-dumpmachine ${CMAKE_C_FLAGS}" OUTPUT_VARIABLE Machine ) MESSAGE("Machine: ${Machine}") diff --git a/cmake/modules/FindFFTW.cmake b/cmake/modules/FindFFTW.cmake new file mode 100644 index 000000000..a7f7c153a --- /dev/null +++ b/cmake/modules/FindFFTW.cmake @@ -0,0 +1,47 @@ +# FindFFTW.cmake - Try to find FFTW3 +# Copyright (c) 2018 Lukas W +# This file is MIT licensed. +# See http://opensource.org/licenses/MIT + +# Try pkgconfig for hints +find_package(PkgConfig QUIET) + +if(NOT FFTW_FIND_COMPONENTS) + set(FFTW_FIND_COMPONENTS fftw3f fftw3 fftwl) +endif() + +if(PKG_CONFIG_FOUND) + pkg_check_modules(FFTW_PKG QUIET fftw>=3.0.0) + pkg_check_modules(FFTW3_PKG QUIET fftw3>=3.0.0) +endif() + +find_path(FFTW_INCLUDE_DIR + NAMES fftw3.h + PATHS ${FFTW_PKG_INCLUDE_DIRS} ${FFTW3_PKG_INCLUDE_DIRS} +) + +set(check_list) + +foreach(comp ${FFTW_FIND_COMPONENTS}) + string(TOUPPER ${comp} COMP) + if(PKG_CONFIG_FOUND) + pkg_check_modules(${COMP}_PKG QUIET ${comp}>=3.0.0) + endif() + + find_library(${COMP}_LIBRARY + NAMES ${comp} + PATHS ${comp}_PKG_LIBRARY_DIRS + ) + list(APPEND check_list ${COMP}_LIBRARY) + + set(${COMP}_LIBRARIES ${${COMP}_LIBRARY} CACHE FILEPATH "${COMP} library path") + set(${COMP}_INCLUDE_DIRS ${FFTW_INCLUDE_DIR} CACHE PATH "${COMP} include path") + mark_as_advanced(${COMP}_LIBRARIES ${COMP}_INCLUDE_DIRS) +endforeach() + +find_package(PackageHandleStandardArgs) +find_package_handle_standard_args(FFTW DEFAULT_MSG FFTW_INCLUDE_DIR ${check_list}) + +set(FFTW_INCLUDE_DIRS ${FFTW_INCLUDE_DIR}) + +mark_as_advanced(FFTW_LIBRARY FFTW_LIBRARIES FFTW_INCLUDE_DIR FFTW_INCLUDE_DIRS ${check_list}) diff --git a/cmake/modules/FindSamplerate.cmake b/cmake/modules/FindSamplerate.cmake new file mode 100644 index 000000000..53b69f6c7 --- /dev/null +++ b/cmake/modules/FindSamplerate.cmake @@ -0,0 +1,34 @@ +# FindFFTW.cmake - Try to find FFTW3 +# Copyright (c) 2018 Lukas W +# This file is MIT licensed. +# See http://opensource.org/licenses/MIT + +find_package(PkgConfig QUIET) +if(PKG_CONFIG_FOUND) + pkg_check_modules(SAMPLERATE_PKG samplerate) +endif() + +find_path(SAMPLERATE_INCLUDE_DIR + NAMES samplerate.h + PATHS ${SAMPLERATE_PKG_INCLUDE_DIRS} +) + +set(SAMPLERATE_NAMES samplerate libsamplerate) +if(Samplerate_FIND_VERSION_MAJOR) + list(APPEND SAMPLERATE_NAMES libsamplerate-${Samplerate_FIND_VERSION_MAJOR}) +else() + list(APPEND SAMPLERATE_NAMES libsamplerate-0) +endif() + +find_library(SAMPLERATE_LIBRARY + NAMES ${SAMPLERATE_NAMES} + PATHS ${SAMPLERATE_PKG_LIBRARY_DIRS} +) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(SAMPLERATE DEFAULT_MSG SAMPLERATE_LIBRARY SAMPLERATE_INCLUDE_DIR) + +mark_as_advanced(SAMPLERATE_INCLUDE_DIR SAMPLERATE_LIBRARY ) + +set(SAMPLERATE_LIBRARIES ${SAMPLERATE_LIBRARY} ) +set(SAMPLERATE_INCLUDE_DIRS ${SAMPLERATE_INCLUDE_DIR}) diff --git a/cmake/modules/FindSndFile.cmake b/cmake/modules/FindSndFile.cmake new file mode 100644 index 000000000..28ebb7bb7 --- /dev/null +++ b/cmake/modules/FindSndFile.cmake @@ -0,0 +1,39 @@ +# FindSndFile.cmake - Try to find libsndfile +# Copyright (c) 2018 Lukas W +# This file is MIT licensed. +# See http://opensource.org/licenses/MIT + +# Try pkgconfig for hints +find_package(PkgConfig QUIET) +if(PKG_CONFIG_FOUND) + pkg_check_modules(SNDFILE_PKG sndfile) +endif(PKG_CONFIG_FOUND) +set(SndFile_DEFINITIONS ${SNDFILE_PKG_CFLAGS_OTHER}) + +if(WIN32) + # Try Vcpkg + find_package(LibSndFile ${SndFile_FIND_VERSION} CONFIG QUIET) + if(LibSndFile_FOUND) + get_target_property(LibSndFile_Location sndfile-shared LOCATION) + get_target_property(LibSndFile_Include_Path sndfile-shared INTERFACE_INCLUDE_DIRECTORIES) + get_filename_component(LibSndFile_Path LibSndFile_Location PATH) + endif() +endif() + +find_path(SNDFILE_INCLUDE_DIR + NAMES sndfile.h + PATHS ${SNDFILE_PKG_INCLUDE_DIRS} ${LibSndFile_Include_Path} +) + +find_library(SNDFILE_LIBRARY + NAMES sndfile libsndfile libsndfile-1 + PATHS ${SNDFILE_PKG_LIBRARY_DIRS} ${LibSndFile_Path} +) + +find_package(PackageHandleStandardArgs) +find_package_handle_standard_args(SndFile DEFAULT_MSG SNDFILE_LIBRARY SNDFILE_INCLUDE_DIR) + +set(SNDFILE_LIBRARIES ${SNDFILE_LIBRARY}) +set(SNDFILE_INCLUDE_DIRS ${SNDFILE_INCLUDE_DIR}) + +mark_as_advanced(SNDFILE_LIBRARY SNDFILE_LIBRARIES SNDFILE_INCLUDE_DIR SNDFILE_INCLUDE_DIRS) diff --git a/cmake/modules/FindSndio.cmake b/cmake/modules/FindSndio.cmake index bf5b24c39..e993702c2 100644 --- a/cmake/modules/FindSndio.cmake +++ b/cmake/modules/FindSndio.cmake @@ -19,14 +19,16 @@ if(SNDIO_LIBRARY) get_filename_component(SNDIO_LIBRARY_DIR ${SNDIO_LIBRARY} PATH) endif(SNDIO_LIBRARY) -check_library_exists(sndio sio_open "${SNDIO_LIBRARY_DIR}" HAVE_SNDIO) -if(HAVE_SNDIO) - message(STATUS "Found sndio: ${SNDIO_LIBRARY}") -else(HAVE_SNDIO) - message(STATUS "sndio not found") -endif(HAVE_SNDIO) -set(SNDIO_FOUND ${HAVE_SNDIO}) +check_library_exists(sndio sio_open "${SNDIO_LIBRARY_DIR}" HAVE_SIO_OPEN) -find_path(SNDIO_INCLUDES sndio.h) +find_path(SNDIO_INCLUDE_DIR sndio.h) -mark_as_advanced(SNDIO_INCLUDES SNDIO_LIBRARY) +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(SNDIO DEFAULT_MSG SNDIO_LIBRARY SNDIO_INCLUDE_DIR HAVE_SIO_OPEN) + +if(SNDIO_FOUND) + set(SNDIO_INCLUDE_DIRS "${SNDIO_INCLUDE_DIR}") + set(SNDIO_LIBRARIES "${SNDIO_LIBRARY}") +endif() + +mark_as_advanced(SNDIO_INCLUDE_DIR SNDIO_LIBRARY SNDIO_INCLUDE_DIRS SNDIO_LIBRARIES) diff --git a/cmake/modules/FindWine.cmake b/cmake/modules/FindWine.cmake index 9967dd9ba..50bf54edb 100644 --- a/cmake/modules/FindWine.cmake +++ b/cmake/modules/FindWine.cmake @@ -7,38 +7,115 @@ # WINE_DEFINITIONS - Compiler switches required for using wine # +MACRO(_findwine_find_flags output expression result) + STRING(REPLACE " " ";" WINEBUILD_FLAGS "${output}") + FOREACH(FLAG ${WINEBUILD_FLAGS}) + IF("${FLAG}" MATCHES "${expression}") + SET(${result} "${FLAG}") + ENDIF() + ENDFOREACH() +ENDMACRO() + LIST(APPEND CMAKE_PREFIX_PATH /opt/wine-stable /opt/wine-devel /opt/wine-staging /usr/lib/wine/) -FIND_PATH(WINE_INCLUDE_DIR windows/windows.h PATH_SUFFIXES wine wine/wine) -FIND_LIBRARY(WINE_LIBRARY NAMES wine PATH_SUFFIXES wine i386-linux-gnu/wine) FIND_PROGRAM(WINE_CXX NAMES wineg++ winegcc winegcc64 winegcc32 winegcc-stable - PATHS /usr/lib/wine) + PATHS /usr/lib/wine +) +FIND_PROGRAM(WINE_BUILD NAMES winebuild) +# Detect wine paths and handle linking problems +IF(WINE_CXX) + EXEC_PROGRAM(${WINE_CXX} ARGS "-m32 -v /dev/zero" OUTPUT_VARIABLE WINEBUILD_OUTPUT_32) + EXEC_PROGRAM(${WINE_CXX} ARGS "-m64 -v /dev/zero" OUTPUT_VARIABLE WINEBUILD_OUTPUT_64) + _findwine_find_flags("${WINEBUILD_OUTPUT_32}" "^-isystem/usr/include$" BUGGED_WINEGCC) + _findwine_find_flags("${WINEBUILD_OUTPUT_32}" "^-isystem" WINEGCC_INCLUDE_DIR) + _findwine_find_flags("${WINEBUILD_OUTPUT_32}" "libwinecrt0\\.a.*" WINECRT_32) + _findwine_find_flags("${WINEBUILD_OUTPUT_64}" "libwinecrt0\\.a.*" WINECRT_64) + STRING(REGEX REPLACE "^-isystem" "" WINE_INCLUDE_HINT "${WINEGCC_INCLUDE_DIR}") + STRING(REGEX REPLACE "/wine/windows$" "" WINE_INCLUDE_HINT "${WINE_INCLUDE_HINT}") + STRING(REGEX REPLACE "libwinecrt0\\.a.*" "" WINE_32_LIBRARY_DIR "${WINECRT_32}") + STRING(REGEX REPLACE "libwinecrt0\\.a.*" "" WINE_64_LIBRARY_DIR "${WINECRT_64}") + + IF(BUGGED_WINEGCC) + MESSAGE(WARNING "Your winegcc is unusable due to https://bugs.winehq.org/show_bug.cgi?id=46293,\n + Consider either upgrading or downgrading wine.") + RETURN() + ENDIF() + IF(WINE_32_LIBRARY_DIR STREQUAL WINE_64_LIBRARY_DIR) + MESSAGE(STATUS "Old winegcc detected, trying to use workaround linking") + # Fix library search directory according to the target bitness + IF(WINE_32_LIBRARY_DIR MATCHES "/lib/(x86_64|i386)-") + # Debian systems + STRING(REPLACE "/lib/x86_64-" "/lib/i386-" WINE_32_LIBRARY_DIR "${WINE_32_LIBRARY_DIR}") + STRING(REPLACE "/lib/i386-" "/lib/x86_64-" WINE_64_LIBRARY_DIR "${WINE_64_LIBRARY_DIR}") + ELSEIF(WINE_32_LIBRARY_DIR MATCHES "/(lib|lib64)/wine/$") + # WineHQ (/opt/wine-stable, /opt/wine-devel, /opt/wine-staging) + STRING(REGEX REPLACE "/lib64/wine/$" "/lib/wine/" WINE_32_LIBRARY_DIR "${WINE_32_LIBRARY_DIR}") + STRING(REGEX REPLACE "/lib/wine/$" "/lib64/wine/" WINE_64_LIBRARY_DIR "${WINE_64_LIBRARY_DIR}") + ELSEIF(WINE_32_LIBRARY_DIR MATCHES "/lib32/.*/wine/") + # Systems with old multilib layout + STRING(REPLACE "/lib32/" "/lib/" WINE_64_LIBRARY_DIR "${WINE_32_LIBRARY_DIR}") + ELSEIF(WINE_32_LIBRARY_DIR MATCHES "/lib64/.*/wine/") + # We need to test if the corresponding 64bit library directory is lib or lib32 + STRING(REPLACE "/lib64/" "/lib32/" WINE_32_LIBRARY_DIR "${WINE_64_LIBRARY_DIR}") + IF(NOT EXISTS "${WINE_32_LIBRARY_DIR}") + STRING(REPLACE "/lib64/" "/lib/" WINE_32_LIBRARY_DIR "${WINE_64_LIBRARY_DIR}") + ENDIF() + ELSEIF(WINE_32_LIBRARY_DIR MATCHES "/lib/.*/wine/") + # Test if this directory is for 32bit or 64bit + STRING(REPLACE "/lib/" "/lib32/" WINE_32_LIBRARY_DIR "${WINE_64_LIBRARY_DIR}") + IF(NOT EXISTS "${WINE_32_LIBRARY_DIR}") + SET(WINE_32_LIBRARY_DIR "${WINE_64_LIBRARY_DIR}") + STRING(REPLACE "/lib/" "/lib64/" WINE_64_LIBRARY_DIR "${WINE_64_LIBRARY_DIR}") + ENDIF() + ELSE() + MESSAGE(WARNING "Can't detect wine installation layout. You may get some build errors.") + ENDIF() + SET(WINE_LIBRARY_FIX "${WINE_32_LIBRARY_DIR} and ${WINE_64_LIBRARY_DIR}") + ENDIF() +ENDIF() + +FIND_PATH(WINE_INCLUDE_DIR wine/exception.h + HINTS "${WINE_INCLUDE_HINT}" +) + +SET(_ARCHITECTURE ${CMAKE_LIBRARY_ARCHITECTURE}) + +FIND_LIBRARY(WINE_LIBRARY NAMES wine + PATH_SUFFIXES wine i386-linux-gnu/wine + HINTS "${WINE_32_LIBRARY_DIR}" "${WINE_64_LIBRARY_DIR}" +) + +SET(CMAKE_LIBRARY_ARCHITECTURE ${_ARCHITECTURE}) SET(WINE_INCLUDE_DIRS ${WINE_INCLUDE_DIR} ) -SET(WINE_LIBRARIES ${WINE_LIBRARY} ) - -# Handle wine linking problems -EXEC_PROGRAM(${WINE_CXX} ARGS "-v -m32 /dev/zero" OUTPUT_VARIABLE WINEBUILD_OUTPUT) -STRING(REPLACE " " ";" WINEBUILD_FLAGS "${WINEBUILD_OUTPUT}") - -FOREACH(FLAG ${WINEBUILD_FLAGS}) - IF("${FLAG}" MATCHES "libwinecrt0.a.*") - # Debian systems - STRING(REPLACE "/lib/x86_64-" "/lib/i386-" FLAG "${FLAG}") - # Fedora systems - STRING(REPLACE "/lib/lib64" "/lib/i386" FLAG "${FLAG}") - # Gentoo systems - STRING(REPLACE "/lib/wine-" "/lib32/wine-" FLAG "${FLAG}") - # WineHQ (/opt/wine-stable, /opt/wine-devel, /opt/wine-staging) - STRING(REPLACE "/lib64/wine/" "/lib/wine/" FLAG "${FLAG}") - - STRING(REGEX REPLACE "/wine/libwinecrt0.a.*" "" WINE_LIBRARY_FIX "${FLAG}") - SET(WINE_LIBRARY_FIX "${WINE_LIBRARY_FIX}/") - ENDIF() -ENDFOREACH() +SET(WINE_LIBRARIES ${WINE_LIBRARY}) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(Wine DEFAULT_MSG WINE_CXX WINE_LIBRARIES WINE_INCLUDE_DIRS) -mark_as_advanced(WINE_INCLUDE_DIR WINE_LIBRARY) +mark_as_advanced(WINE_INCLUDE_DIR WINE_LIBRARY WINE_CXX WINE_BUILD) + +IF(WINE_32_LIBRARY_DIR) + IF(WINE_32_LIBRARY_DIR MATCHES "wine*/lib") + SET(WINE_32_FLAGS "-L${WINE_32_LIBRARY_DIR} -L${WINE_32_LIBRARY_DIR}../") + SET(WINE_32_LIBRARY_DIRS "${WINE_32_LIBRARY_DIR}:${WINE_32_LIBRARY_DIR}/..") + ELSE() + SET(WINE_32_FLAGS "-L${WINE_32_LIBRARY_DIR}") + SET(WINE_32_LIBRARY_DIRS "${WINE_32_LIBRARY_DIR}") + ENDIF() +ENDIF() + +IF(WINE_64_LIBRARY_DIR) + IF(WINE_64_LIBRARY_DIR MATCHES "wine*/lib") + SET(WINE_64_FLAGS "-L${WINE_64_LIBRARY_DIR} -L${WINE_64_LIBRARY_DIR}../") + SET(WINE_64_LIBRARY_DIRS "${WINE_64_LIBRARY_DIR}:${WINE_64_LIBRARY_DIR}/..") + ELSE() + SET(WINE_64_FLAGS "-L${WINE_64_LIBRARY_DIR}") + SET(WINE_64_LIBRARY_DIRS "${WINE_64_LIBRARY_DIR}") + ENDIF() +ENDIF() + +# Create winegcc wrapper +configure_file(${CMAKE_CURRENT_LIST_DIR}/winegcc_wrapper.in winegcc_wrapper @ONLY) +SET(WINEGCC "${CMAKE_CURRENT_BINARY_DIR}/winegcc_wrapper") diff --git a/cmake/modules/InstallDependencies.cmake b/cmake/modules/InstallDependencies.cmake new file mode 100644 index 000000000..791041bb2 --- /dev/null +++ b/cmake/modules/InstallDependencies.cmake @@ -0,0 +1,184 @@ +include(GetPrerequisites) +include(CMakeParseArguments) + +CMAKE_POLICY(SET CMP0011 NEW) +CMAKE_POLICY(SET CMP0057 NEW) + +function(make_absolute var) + get_filename_component(abs "${${var}}" ABSOLUTE BASE_DIR "${CMAKE_INSTALL_PREFIX}") + set(${var} ${abs} PARENT_SCOPE) +endfunction() + +# Reads lines of a file into a list, skipping '#' comment lines +function(READ_LIST_FILE FILE VAR) + file(STRINGS "${FILE}" list) + + set(result "") + foreach(item ${list}) + string(STRIP "${item}" item) + if(item STREQUAL "" OR item MATCHES "^\#") + continue() + endif() + list(APPEND result "${item}") + endforeach() + + set(${VAR} ${result} PARENT_SCOPE) +endfunction() + +function(make_all_absolute list_var) + set(result "") + foreach(file ${${list_var}}) + make_absolute(file) + list(APPEND result ${file}) + endforeach() + set(${list_var} ${result} PARENT_SCOPE) +endfunction() + +if(CMAKE_BINARY_DIR) + set(tmp_lib_dir "${CMAKE_BINARY_DIR}/bundled-libraries") +elseif(CMAKE_HOST_UNIX) + set(tmp_lib_dir "/tmp/bundled-libraries") +elseif(DEFINED ENV{TEMP}) + set(tmp_lib_dir "$ENV{TMP}/bundled-libraries") +else() + message(FATAL_ERROR "Can't find a temp dir for libraries") +endif() + +# Like file(INSTALL), but resolves symlinks +function(install_file_resolved file destination) + + get_filename_component(file_name "${file}" NAME) + if(IS_SYMLINK "${file}") + get_filename_component(real_path "${file}" REALPATH) + get_filename_component(real_name "${real_path}" NAME) + file(COPY "${real_path}" DESTINATION "${tmp_lib_dir}") + file(RENAME "${tmp_lib_dir}/${real_name}" "${tmp_lib_dir}/${file_name}") + set(file_path "${tmp_lib_dir}/${file_name}") + else() + set(file_path "${file}") + endif() + + file(INSTALL "${file_path}" DESTINATION "${destination}") +endfunction() + +function(install_resolved) + cmake_parse_arguments("" "" "DESTINATION" "FILES" ${ARGN}) + foreach(file ${_FILES}) + install_file_resolved("${file}" "${_DESTINATION}") + endforeach() +endfunction() + +if(CMAKE_CROSSCOMPILING) + # If we're cross-compiling, GetPrerequisites may not be able to find system libraries such as kernel32.dll because + # they're supplied by the toolchain. To suppress thousands of lines of warnings being printed to the console, we + # override gp_resolved_file_type to return "system" for any library in ${IGNORE_LIBS} without trying to resolve the + # file first. + # GetPrerequisites supports using an override function called gp_resolved_file_type_override, but it's not suited + # for our purpose because it's only called by gp_resolved_file_type *after* trying to resolve the file. + function(gp_resolved_file_type original_file file exepath dirs type_var) + set(file_find "${file}") + if(_IGNORE_CASE) + # On case-insensitive systems, convert to upper characters to respect it + string(TOUPPER "${file_find}" file_find) + endif() + SET(IGNORE_LIBS ${_IGNORE_LIBS} CACHE INTERNAL "Ignored library names" FORCE) + if(IGNORE_LIBS AND ${file_find} IN_LIST IGNORE_LIBS) + set(${type_var} system PARENT_SCOPE) + else() + #_gp_resolved_file_type(${ARGV}) + _gp_resolved_file_type("${original_file}" "${file}" "${exepath}" "${dirs}" "${type_var}" ${ARGN}) + endif() + endfunction() +endif() + +function(INSTALL_DEPENDENCIES) + cmake_parse_arguments("" "INCLUDE_SYSTEM;IGNORE_CASE" "GP_TOOL;DESTINATION;IGNORE_LIBS_FILE" "FILES;LIB_DIRS;SEARCH_PATHS;IGNORE_LIBS" ${ARGN}) + + # Make paths absolute + make_absolute(_DESTINATION) + make_all_absolute(_FILES) + make_all_absolute(_LIB_DIRS) + make_all_absolute(_SEARCH_PATHS) + + if(_INCLUDE_SYSTEM) + set(EXCLUDE_SYSTEM 0) + else() + set(EXCLUDE_SYSTEM 1) + endif() + + if(_IGNORE_LIBS_FILE) + READ_LIST_FILE("${_IGNORE_LIBS_FILE}" _IGNORE_LIBS) + if(_IGNORE_CASE) + # On case-insensitive systems, convert to upper characters to respect it + string(TOUPPER "${_IGNORE_LIBS}" _IGNORE_LIBS) + endif() + SET(IGNORE_LIBS ${_IGNORE_LIBS} CACHE INTERNAL "Ignored library names" FORCE) + endif() + + if(_GP_TOOL) + set(gp_tool "${_GP_TOOL}") + endif() + + set(prereqs "") + foreach(file ${_FILES}) + get_filename_component(file_name "${file}" NAME) + message("-- Finding prerequisites of ${file_name}") + find_prerequisites("${file}" _prereqs + ${EXCLUDE_SYSTEM} # exclude system files + 1 # recurse + "" + "${_LIB_DIRS}" + "${_SEARCH_PATHS}" + "${_IGNORE_LIBS}" + ) + + list(APPEND prereqs ${_prereqs}) + endforeach() + + list(REMOVE_DUPLICATES prereqs) + + foreach(prereq ${prereqs}) + get_filename_component(prereq_name "${prereq}" NAME) + + foreach(rpath ${_SEARCH_PATHS}) + if(EXISTS "${rpath}/${prereq_name}") + list(REMOVE_ITEM prereqs "${prereq}") + break() + endif() + endforeach() + endforeach() + + #file(INSTALL ${prereqs} DESTINATION ${_DESTINATION}) + install_resolved(FILES ${prereqs} DESTINATION "${_DESTINATION}") +endfunction() + +# Like get_prerequisites, but returns full paths +function(FIND_PREREQUISITES target RESULT_VAR exclude_system recurse + exepath dirs rpaths) + set(RESULTS) + + get_prerequisites("${target}" _prereqs ${exclude_system} ${recurse} + "" "${dirs}" "${rpaths}") + + foreach(prereq ${_prereqs}) + get_filename_component(prereq_name "${prereq}" NAME) + if(_IGNORE_CASE) + # Windows is case insensitive. + # Use upper characters to respect it. + string(TOUPPER "${prereq_name}" prereq_name) + endif() + if("${prereq_name}" IN_LIST IGNORE_LIBS) + continue() + endif() + + gp_resolve_item("${LIB_DLL}" "${prereq}" "" "${dirs}" RESOLVED_PREREQ "${rpaths}") + + if(RESOLVED_PREREQ AND IS_ABSOLUTE ${RESOLVED_PREREQ} AND EXISTS ${RESOLVED_PREREQ}) + list(APPEND RESULTS ${RESOLVED_PREREQ}) + else() + message(FATAL_ERROR "Can't resolve dependency ${prereq}.") + endif() + endforeach() + + set(${RESULT_VAR} ${RESULTS} PARENT_SCOPE) +endfunction() diff --git a/cmake/modules/InstallTargetDependencies.cmake b/cmake/modules/InstallTargetDependencies.cmake new file mode 100644 index 000000000..9665a0b87 --- /dev/null +++ b/cmake/modules/InstallTargetDependencies.cmake @@ -0,0 +1,89 @@ +include(DefineInstallVar) + +SET(DEFAULT_SEARCH_DIRECTORIES "${BIN_DIR}" "${LIB_DIR}" "${CMAKE_FIND_ROOT_PATH}" "${CMAKE_PREFIX_PATH}") +SET(DEFAULT_SEARCH_SUFFIXES "bin" "lib" "../bin") + +# Like INSTALL_DEPENDENCIES but can be called from regular cmake code +# (instead of install(CODE)), takes targets instead of files, +# takes care of configuring search paths, and other platform-specific tweaks. +# Arguments: +# TARGETS: list of cmake targets to install. +# NAME: unique string for this install. +# DESTINATION: directory path to install the binaries to. +# LIB_DIRS: list of paths for looking up dependencies. +# LIB_DIRS_SUFFIXES: list of possible suffixes for LIB_DIRS entries. +# NO_DEFAULT_PATHS: supply this value to avoid adding DEFAULT_SEARCH_DIRECTORIES +# to LIB_DIRS and DEFAULT_SEARCH_SUFFIXES to LIB_DIRS_SUFFIXES. +FUNCTION(INSTALL_TARGET_DEPENDENCIES) + set(options NO_DEFAULT_PATHS) + set(oneValueArgs NAME) + set(multiValueArgs TARGETS DESTINATION LIB_DIRS_SUFFIXES LIB_DIRS) + cmake_parse_arguments(DEPS "${options}" "${oneValueArgs}" + "${multiValueArgs}" ${ARGN} ) + + if(NOT DEPS_LIB_DIRS) + set(DEPS_LIB_DIRS "") + endif() + + # Set default values. + if(NOT DEPS_NO_DEFAULT_PATHS) + list(APPEND DEPS_LIB_DIRS ${DEFAULT_SEARCH_DIRECTORIES}) + set(DEPS_LIB_DIRS_SUFFIXES "${DEPS_LIB_DIRS_SUFFIXES}" ${DEFAULT_SEARCH_SUFFIXES}) + endif() + + FOREACH(TARGET ${DEPS_TARGETS}) + IF(NOT TARGET ${TARGET}) + message(FATAL_ERROR "Not a target: ${TARGET}") + ENDIF() + + # Collect target output files. + LIST(APPEND DEPLOY_TARGETS "$") + + # Collect target link directories + get_target_property(target_libs ${TARGET} LINK_LIBRARIES) + + foreach(lib ${target_libs}) + if(TARGET ${lib} OR NOT IS_ABSOLUTE ${lib}) + continue() + endif() + + get_filename_component(lib_dir ${lib} PATH) + list(APPEND DEPS_LIB_DIRS ${lib_dir}) + endforeach() + ENDFOREACH() + + LIST(APPEND DEPS_LIB_DIRS ${CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES}) + + FOREACH(LIB_PATH ${DEPS_LIB_DIRS}) + FOREACH(suffix ${DEPS_LIB_DIRS_SUFFIXES}) + list(APPEND DEPS_LIB_DIRS "${LIB_PATH}/${suffix}") + ENDFOREACH() + ENDFOREACH() + + DEFINE_INSTALL_VAR(NAME "DEPLOY_FILES" CONTENT "${DEPLOY_TARGETS}" GENERATOR_EXPRESSION) + + LIST(REMOVE_DUPLICATES DEPS_LIB_DIRS) + + IF(LMMS_BUILD_LINUX) + FILE(DOWNLOAD "https://raw.githubusercontent.com/AppImage/AppImages/master/excludelist" + "${CMAKE_BINARY_DIR}/excludelist") + SET(additional_args INCLUDE_SYSTEM IGNORE_LIBS_FILE ${CMAKE_BINARY_DIR}/excludelist) + ELSEIF(LMMS_BUILD_WIN32) + SET(additional_args IGNORE_CASE IGNORE_LIBS_FILE "${LMMS_SOURCE_DIR}/cmake/install/excludelist-win") + IF(CMAKE_CROSSCOMPILING) + SET(additional_args "${additional_args}" GP_TOOL objdump) + ENDIF() + ENDIF() + + INSTALL(CODE " + INCLUDE(\"${LMMS_SOURCE_DIR}/cmake/modules/InstallDependencies.cmake\") + + INSTALL_DEPENDENCIES( + FILES \"\${DEPLOY_FILES}\" + DESTINATION \"${DEPS_DESTINATION}\" + LIB_DIRS \"${DEPS_LIB_DIRS}\" + SEARCH_PATHS \"${DEPS_SEARCH_PATHS}\" + ${additional_args} + ) + ") +ENDFUNCTION() diff --git a/cmake/modules/PluginList.cmake b/cmake/modules/PluginList.cmake new file mode 100644 index 000000000..c82bba329 --- /dev/null +++ b/cmake/modules/PluginList.cmake @@ -0,0 +1,104 @@ +# Provides a fast mechanism for filtering the plugins used at build-time +SET(PLUGIN_LIST "" CACHE STRING "List of plug-ins to build") +STRING(REPLACE " " ";" PLUGIN_LIST "${PLUGIN_LIST}") +OPTION(LMMS_MINIMAL "Build a minimal list of plug-ins" OFF) +OPTION(LIST_PLUGINS "Lists the available plugins for building" OFF) + +SET(MINIMAL_LIST + audio_file_processor + kicker + triple_oscillator +) + +IF(LMMS_MINIMAL) + IF("${PLUGIN_LIST}" STREQUAL "") + STRING(REPLACE ";" " " MINIMAL_LIST_STRING "${MINIMAL_LIST}") + MESSAGE( +"-- Using minimal plug-ins: ${MINIMAL_LIST_STRING}\n" +" Note: You can specify specific plug-ins using -DPLUGIN_LIST=\"foo bar\"" + ) + ENDIF() + SET(PLUGIN_LIST ${MINIMAL_LIST} ${PLUGIN_LIST}) +ENDIF() + +SET(LMMS_PLUGIN_LIST + ${MINIMAL_LIST} + Amplifier + BassBooster + bit_invader + Bitcrush + carlabase + carlapatchbay + carlarack + CrossoverEQ + Delay + DualFilter + dynamics_processor + Eq + Flanger + HydrogenImport + ladspa_browser + LadspaEffect + lb302 + MidiImport + MidiExport + MultitapEcho + monstro + nes + OpulenZ + organic + FreeBoy + patman + peak_controller_effect + GigPlayer + ReverbSC + sf2_player + sfxr + sid + SpectrumAnalyzer + stereo_enhancer + stereo_matrix + stk + vst_base + vestige + VstEffect + watsyn + waveshaper + vibed + Xpressive + zynaddsubfx +) + +IF("${PLUGIN_LIST}" STREQUAL "") + SET(PLUGIN_LIST ${LMMS_PLUGIN_LIST}) +ENDIF() + +MACRO(LIST_ALL_PLUGINS) + MESSAGE("\n\nAll possible -DPLUGIN_LIST values") + MESSAGE("\n KEYWORD:") + MESSAGE(" -DLMMS_MINIMAL=True") + FOREACH(item IN LISTS MINIMAL_LIST) + MESSAGE(" ${item}") + ENDFOREACH() + MESSAGE("\n NAME:") + FOREACH(item IN LISTS LMMS_PLUGIN_LIST) + MESSAGE(" ${item}") + ENDFOREACH() + MESSAGE("\nNote: This value also impacts the fetching of git submodules.\n") + MESSAGE(FATAL_ERROR "Information was requested, aborting build!") +ENDMACRO() + +IF(LIST_PLUGINS) + UNSET(LIST_PLUGINS CACHE) + LIST_ALL_PLUGINS() +ENDIF() + +IF(MSVC) + SET(MSVC_INCOMPATIBLE_PLUGINS + LadspaEffect + zynaddsubfx + ) + message(WARNING "Compiling with MSVC. The following plugins are not available: ${MSVC_INCOMPATIBLE_PLUGINS}") + LIST(REMOVE_ITEM PLUGIN_LIST ${MSVC_INCOMPATIBLE_PLUGINS}) +ENDIF() + diff --git a/cmake/modules/winegcc_wrapper.in b/cmake/modules/winegcc_wrapper.in new file mode 100755 index 000000000..7677e4c37 --- /dev/null +++ b/cmake/modules/winegcc_wrapper.in @@ -0,0 +1,77 @@ +#!/bin/sh +# Wrapper script for winegcc to remove .exe file ending automatically +# appended by winebuild. +# See FindWine.cmake for usage + +set -e + +args="$@" + +# Find output name, link mode and architecture +while [ $# -gt 0 ]; do + key="$1" + + case $key in + -o) + output=$2 + shift + ;; + -c) + no_link=true + ;; + -m32) + win32=true + ;; + -m64) + win64=true + ;; + *) + + ;; + esac + + shift +done + +if [ -z "$output" ]; then + # If -c is used without specifying an output name, GCC defaults to "a.out". + if [ "$no_link" != true ]; then + output="a.out" + no_move=true + fi +fi + +# Some Wine distributions can't find their own headers. WINE_INCLUDE_DIR provided +# by FindWine.cmake +extra_args="-I@WINE_INCLUDE_DIR@ -I@WINE_INCLUDE_DIR@/wine/windows" + +# Apply manually specified flags +extra_args="$extra_args @WINE_CXX_FLAGS@" + +# Apply -m32 library fix if necessary +if [ "$win32" = true ] && [ "$no_link" != true ]; then + extra_args="$extra_args @WINE_32_FLAGS@" +fi + +# Apply -m64 library fix if necessary +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 + +if [ "$no_move" = true ] || [ "$no_link" = true ]; then + exit 0 +fi + +if [ ! -e "$output.exe" ]; then + echo "Fatal error in winegcc wrapper: No output file \"$output.exe\" found." + exit 1 +fi + +mv $output.exe $output diff --git a/cmake/nsis/CMakeLists.txt b/cmake/nsis/CMakeLists.txt index b21c920e5..3fcb4b2f3 100644 --- a/cmake/nsis/CMakeLists.txt +++ b/cmake/nsis/CMakeLists.txt @@ -1,5 +1,13 @@ +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") -SET(CPACK_NSIS_MUI_ICON "${CMAKE_SOURCE_DIR}/cmake/nsis/lmms.ico") +IF(MSVC) + STRING(REPLACE "/" "\\\\" CPACK_PACKAGE_ICON ${CPACK_PACKAGE_ICON}) +ENDIF(MSVC) +SET(CPACK_NSIS_MUI_ICON "${CMAKE_SOURCE_DIR}/cmake/nsis/icon.ico") SET(CPACK_NSIS_INSTALLED_ICON_NAME "${CMAKE_PROJECT_NAME}.exe" PARENT_SCOPE) SET(CPACK_NSIS_DISPLAY_NAME "${PROJECT_NAME_UCASE} ${VERSION}" PARENT_SCOPE) SET(CPACK_NSIS_HELP_LINK "${PROJECT_URL}" PARENT_SCOPE) @@ -8,10 +16,11 @@ SET(CPACK_NSIS_CONTACT "${PROJECT_EMAIL}" PARENT_SCOPE) SET(CPACK_PACKAGE_EXECUTABLES "${CMAKE_PROJECT_NAME}.exe;${PROJECT_NAME_UCASE}" PARENT_SCOPE) SET(CPACK_NSIS_MENU_LINKS "${CMAKE_PROJECT_NAME}.exe;${PROJECT_NAME_UCASE}" PARENT_SCOPE) SET(CPACK_NSIS_DEFINES " - !include ${CMAKE_SOURCE_DIR}/cmake/nsis/FileAssociation.nsh + !addincludedir ${CMAKE_SOURCE_DIR}/cmake/nsis + !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)\\\" @@ -27,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} @@ -37,10 +46,10 @@ ENDIF() # Fix windows paths for msys IF(LMMS_BUILD_MSYS) - STRING(REGEX REPLACE "/" "\\\\\\\\" CPACK_PACKAGE_ICON "${CPACK_PACKAGE_ICON}") - STRING(REGEX REPLACE "/" "\\\\\\\\" CPACK_NSIS_MUI_ICON "${CPACK_NSIS_MUI_ICON}") - STRING(REGEX REPLACE "/" "\\\\\\\\" CPACK_NSIS_DEFINES "${CPACK_NSIS_DEFINES}") - STRING(REGEX REPLACE "/" "\\\\\\\\" CMAKE_BINARY_DIR_FIX "${CMAKE_BINARY_DIR}") + STRING(REPLACE "/" "\\\\" CPACK_PACKAGE_ICON "${CPACK_PACKAGE_ICON}") + STRING(REPLACE "/" "\\\\" CPACK_NSIS_MUI_ICON "${CPACK_NSIS_MUI_ICON}") + STRING(REPLACE "/" "\\\\" CPACK_NSIS_DEFINES "${CPACK_NSIS_DEFINES}") + STRING(REPLACE "/" "\\\\" CMAKE_BINARY_DIR_FIX "${CMAKE_BINARY_DIR}") # FIXME: there's no easy way to fix $INST_DIR, so we'll redefine it manually IF(WIN64) @@ -71,3 +80,5 @@ IF(LMMS_HAVE_STK) ENDIF() INSTALL(FILES "lmms.exe.manifest" DESTINATION .) +INSTALL(FILES "lmms.VisualElementsManifest.xml" DESTINATION .) +INSTALL(DIRECTORY "assets" DESTINATION .) diff --git a/cmake/nsis/FileAssociation.nsh b/cmake/nsis/FileAssociation.nsh index 061df6c4f..2ae430504 100644 --- a/cmake/nsis/FileAssociation.nsh +++ b/cmake/nsis/FileAssociation.nsh @@ -129,6 +129,7 @@ NoBackup: WriteRegStr HKCR "$R0" "" "$R0" WriteRegStr HKCR "$R0\shell" "" "open" Skip: + WriteRegStr HKCR "$R0\DefaultIcon" "" "$R2,1" WriteRegStr HKCR "$R0\shell\open\command" "" '"$R2" "%1"' WriteRegStr HKCR "$R0\shell\edit" "" "Edit $R0" WriteRegStr HKCR "$R0\shell\edit\command" "" '"$R2" "%1"' diff --git a/cmake/nsis/assets/Logo.png b/cmake/nsis/assets/Logo.png new file mode 100644 index 000000000..e1566b218 Binary files /dev/null and b/cmake/nsis/assets/Logo.png differ diff --git a/cmake/nsis/assets/SmallLogo.png b/cmake/nsis/assets/SmallLogo.png new file mode 100644 index 000000000..23d44ee28 Binary files /dev/null and b/cmake/nsis/assets/SmallLogo.png differ diff --git a/cmake/nsis/icon.ico b/cmake/nsis/icon.ico new file mode 100644 index 000000000..96125a1bb Binary files /dev/null and b/cmake/nsis/icon.ico differ diff --git a/cmake/nsis/lmms.VisualElementsManifest.xml b/cmake/nsis/lmms.VisualElementsManifest.xml new file mode 100644 index 000000000..6bda439b0 --- /dev/null +++ b/cmake/nsis/lmms.VisualElementsManifest.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/cmake/nsis/lmms.ico b/cmake/nsis/lmms.ico deleted file mode 100644 index 9ee65b86d..000000000 Binary files a/cmake/nsis/lmms.ico and /dev/null differ diff --git a/cmake/nsis/lmms.rc.in b/cmake/nsis/lmms.rc.in index f153ee235..a3723b20d 100644 --- a/cmake/nsis/lmms.rc.in +++ b/cmake/nsis/lmms.rc.in @@ -1,4 +1,5 @@ -lmmsicon ICON cmake/nsis/lmms.ico +lmmsicon ICON cmake/nsis/icon.ico +lmmsprojecticon ICON cmake/nsis/project.ico #include VS_VERSION_INFO VERSIONINFO diff --git a/cmake/nsis/nsis_branding.bmp b/cmake/nsis/nsis_branding.bmp index a7e75e3c1..939f2ebab 100644 Binary files a/cmake/nsis/nsis_branding.bmp and b/cmake/nsis/nsis_branding.bmp differ diff --git a/cmake/nsis/project.ico b/cmake/nsis/project.ico new file mode 100644 index 000000000..4b994f321 Binary files /dev/null and b/cmake/nsis/project.ico differ diff --git a/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/cmake/toolchains/Ubuntu-MinGW-W64-64.cmake b/cmake/toolchains/Ubuntu-MinGW-W64-64.cmake index e10ae7311..a1b33ec67 100644 --- a/cmake/toolchains/Ubuntu-MinGW-W64-64.cmake +++ b/cmake/toolchains/Ubuntu-MinGW-W64-64.cmake @@ -1,2 +1,4 @@ +SET(CMAKE_TOOLCHAIN_FILE_32 "${CMAKE_CURRENT_LIST_DIR}/Ubuntu-MinGW-W64-32.cmake") + INCLUDE(${CMAKE_CURRENT_LIST_DIR}/common/Win64.cmake) INCLUDE(${CMAKE_CURRENT_LIST_DIR}/common/Ubuntu-MinGW-W64.cmake) diff --git a/cmake/toolchains/Ubuntu-MinGW-X-Trusty-64.cmake b/cmake/toolchains/Ubuntu-MinGW-X-Trusty-64.cmake index 705e41eae..0f448fef5 100644 --- a/cmake/toolchains/Ubuntu-MinGW-X-Trusty-64.cmake +++ b/cmake/toolchains/Ubuntu-MinGW-X-Trusty-64.cmake @@ -3,4 +3,7 @@ SET(MINGW_PREFIX32 /opt/mingw32) SET(WIN64 TRUE) +SET(CMAKE_TOOLCHAIN_FILE_32 "${CMAKE_CURRENT_LIST_DIR}/Ubuntu-MinGW-X-Trusty-32.cmake") +SET(CMAKE_PREFIX_PATH_32 "${MINGW_PREFIX32}") + INCLUDE(${CMAKE_CURRENT_LIST_DIR}/common/Ubuntu-MinGW-X-Trusty.cmake) diff --git a/cmake/toolchains/common/MSYS.cmake b/cmake/toolchains/common/MSYS.cmake index dc295d670..0b27e8d32 100644 --- a/cmake/toolchains/common/MSYS.cmake +++ b/cmake/toolchains/common/MSYS.cmake @@ -2,7 +2,6 @@ SET(CMAKE_FIND_ROOT_PATH ${MINGW_PREFIX}) SET(CMAKE_INSTALL_PREFIX ${MINGW_PREFIX}) - # Windows msys mingw ships with a mostly-suitable preconfigured environment SET(STRIP ${MINGW_PREFIX}/bin/strip) SET(CMAKE_RC_COMPILER ${MINGW_PREFIX}/bin/windres) @@ -20,18 +19,4 @@ ENDIF() SET(CMAKE_C_USE_RESPONSE_FILE_FOR_INCLUDES OFF) SET(CMAKE_CXX_USE_RESPONSE_FILE_FOR_INCLUDES OFF) -# Variable to assist override Qt debug libraries with release versions -SET(QT_OVERRIDE_LIBRARIES - optimized;${MINGW_PREFIX}/bin/QtGui4.dll; - optimized;${MINGW_PREFIX}/bin/QtCore4.dll; - optimized;${MINGW_PREFIX}/bin/QtXml4.dll; - debug;${MINGW_PREFIX}/bin/QtGui4.dll; - debug;${MINGW_PREFIX}/bin/QtCore4.dll; - debug;${MINGW_PREFIX}/bin/QtXml4.dll; -) -IF(LMMS_BUILD_MSYS AND CMAKE_BUILD_TYPE STREQUAL "Debug") - # Override Qt debug libraries with release versions - SET(QT_LIBRARIES "${QT_OVERRIDE_LIBRARIES}") -ENDIF() - -SET(LMMS_BUILD_MSYS 1) \ No newline at end of file +SET(LMMS_BUILD_MSYS 1) diff --git a/cmake/toolchains/common/Ubuntu-MinGW-W64.cmake b/cmake/toolchains/common/Ubuntu-MinGW-W64.cmake index acb2cbf91..2f78a441e 100644 --- a/cmake/toolchains/common/Ubuntu-MinGW-W64.cmake +++ b/cmake/toolchains/common/Ubuntu-MinGW-W64.cmake @@ -6,7 +6,7 @@ set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++) set(CMAKE_RC_COMPILER ${TOOLCHAIN_PREFIX}-windres) set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX}) -SET(PKG_CONFIG_EXECUTABLE /usr/bin/${TOOLCHAIN_PREFIX}-pkg-config) +SET(ENV{PKG_CONFIG} /usr/bin/${TOOLCHAIN_PREFIX}-pkg-config) IF(WIN64) SET(TOOLCHAIN_PREFIX32 ${CMAKE_SYSTEM_PROCESSOR32}-w64-mingw32) diff --git a/cmake/toolchains/common/Ubuntu-MinGW-X-Trusty.cmake b/cmake/toolchains/common/Ubuntu-MinGW-X-Trusty.cmake index 1dabc3555..686f4497f 100644 --- a/cmake/toolchains/common/Ubuntu-MinGW-X-Trusty.cmake +++ b/cmake/toolchains/common/Ubuntu-MinGW-X-Trusty.cmake @@ -19,7 +19,7 @@ SET(CMAKE_RC_COMPILER ${MINGW_TOOL_PREFIX}windres) # Mingw tools SET(STRIP ${MINGW_TOOL_PREFIX}strip) -SET(PKG_CONFIG_EXECUTABLE ${MINGW_TOOL_PREFIX}pkg-config) +SET(ENV{PKG_CONFIG} ${MINGW_TOOL_PREFIX}pkg-config) # For 32-bit vst support IF(WIN64) @@ -45,7 +45,7 @@ IF(NOT DEFINED ENV{MINGW_DEBUG_INFO}) MESSAGE("* CMAKE_C_COMPILER : ${CMAKE_C_COMPILER}") MESSAGE("* CMAKE_CXX_COMPILER : ${CMAKE_CXX_COMPILER}") MESSAGE("* CMAKE_RC_COMPILER : ${CMAKE_RC_COMPILER}") - MESSAGE("* PKG_CONFIG_EXECUTABLE : ${PKG_CONFIG_EXECUTABLE}") + MESSAGE("* ENV{PKG_CONFIG} : $ENV{PKG_CONFIG}") MESSAGE("* MINGW_TOOL_PREFIX32 : ${MINGW_TOOL_PREFIX32}") MESSAGE("* CMAKE_C_COMPILER32 : ${CMAKE_C_COMPILER32}") MESSAGE("* CMAKE_CXX_COMPILER32 : ${CMAKE_CXX_COMPILER32}") diff --git a/cmake/toolchains/common/Win32.cmake b/cmake/toolchains/common/Win32.cmake index 5a6fb103c..bc20775d6 100644 --- a/cmake/toolchains/common/Win32.cmake +++ b/cmake/toolchains/common/Win32.cmake @@ -2,3 +2,5 @@ SET(CMAKE_SYSTEM_NAME Windows) SET(CMAKE_SYSTEM_VERSION 1) SET(CMAKE_SYSTEM_PROCESSOR i686) + +SET(WIN64 FALSE) diff --git a/cmake/uninstall.cmake b/cmake/uninstall.cmake new file mode 100644 index 000000000..6f6260b58 --- /dev/null +++ b/cmake/uninstall.cmake @@ -0,0 +1,76 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 3.3) + +MESSAGE(STATUS "Attempting to create uninstall target for make") + +#Remove all of the files listed in install_manifest.txt +SET(INSTALL_MANIFEST_PATH "${CMAKE_CURRENT_BINARY_DIR}/install_manifest.txt") +IF(NOT EXISTS ${INSTALL_MANIFEST_PATH}) + MESSAGE(FATAL_ERROR "Could not find install manifest at ${CMAKE_CURRENT_BINARY_DIR}/install_manifest.txt\nThis may be because 'make install' has not been run or install_manifest.txt has been deleted") +ENDIF() +MESSAGE(STATUS "install_manifest.txt found") +FILE(STRINGS ${INSTALL_MANIFEST_PATH} FILES_TO_REMOVE) +FOREACH(FILE_TO_REMOVE ${FILES_TO_REMOVE}) + IF(NOT EXISTS "${FILE_TO_REMOVE}") + MESSAGE(WARNING "Could not find file ${FILE_TO_REMOVE}") + CONTINUE() + ENDIF() + + FILE(REMOVE "${FILE_TO_REMOVE}") + IF(NOT EXISTS "${FILE_TO_REMOVE}") + MESSAGE(STATUS "Successfully removed file ${FILE_TO_REMOVE}") + ELSE() + MESSAGE(FATAL_ERROR "Failed to remove file ${FILE_TO_REMOVE}.") + ENDIF() +ENDFOREACH(FILE_TO_REMOVE) + +# Remove empty directories created during installation + +# Checks if a directory is empty and saves the result in out_var +FUNCTION(IS_EMPTY_DIR OUT_VAR DIR) + FILE(GLOB FILES "${DIR}/*") + LIST(LENGTH FILES NUM_FILES) + IF(NUM_FILES EQUAL 0) + SET(${OUT_VAR} TRUE PARENT_SCOPE) + ELSE() + SET(${OUT_VAR} FALSE PARENT_SCOPE) + ENDIF() +ENDFUNCTION() + +# Recursively append all parent directories of path to out_var +FUNCTION(PARENT_DIRECTORIES OUT_VAR PATH) + GET_FILENAME_COMPONENT(PARENT "${PATH}" DIRECTORY) + IF(PARENT AND NOT PARENT STREQUAL PATH AND NOT PARENT IN_LIST ${OUT_VAR}) + LIST(APPEND ${OUT_VAR} ${PARENT}) + PARENT_DIRECTORIES(${OUT_VAR} "${PARENT}") + ENDIF() + SET(${OUT_VAR} ${${OUT_VAR}} PARENT_SCOPE) +ENDFUNCTION() + +# Removes all empty parent directories of the given files +FUNCTION(REMOVE_EMPTY_DIRECTORIES FILES) + SET(DIRECTORIES) + FOREACH(FILE_TO_REMOVE ${FILES}) + PARENT_DIRECTORIES(DIRECTORIES "${FILE_TO_REMOVE}") + endforeach() + LIST(REMOVE_DUPLICATES DIRECTORIES) + # Sort and reverse so we remove subdirectories first + LIST(SORT DIRECTORIES) + LIST(REVERSE DIRECTORIES) + + FOREACH(DIR ${DIRECTORIES}) + # Skip directories not inside the install prefix + IF(NOT (EXISTS "${DIR}" AND DIR MATCHES "^${CMAKE_INSTALL_PREFIX}/")) + CONTINUE() + ENDIF() + + IS_EMPTY_DIR(DIR_EMPTY "${DIR}") + IF(DIR_EMPTY) + MESSAGE(STATUS "Removing empty directory ${DIR}") + FILE(REMOVE_RECURSE "${DIR}") + ELSEIF() + MESSAGE(STATUS "Skipping non-empty directory ${DIR}") + ENDIF() + ENDFOREACH() +ENDFUNCTION() + +REMOVE_EMPTY_DIRECTORIES("${FILES_TO_REMOVE}") diff --git a/data/locale/CMakeLists.txt b/data/locale/CMakeLists.txt index 3c72e7d78..9cb25f426 100644 --- a/data/locale/CMakeLists.txt +++ b/data/locale/CMakeLists.txt @@ -2,12 +2,13 @@ SET(QT_LUPDATE_EXECUTABLE "${Qt5_LUPDATE_EXECUTABLE}") SET(QT_LRELEASE_EXECUTABLE "${Qt5_LRELEASE_EXECUTABLE}") IF(QT_LUPDATE_EXECUTABLE STREQUAL "") - EXECUTE_PROCESS(COMMAND "lupdate" "--help" RESULT_VARIABLE LUPDATE_FALLBACK OUTPUT_QUIET) + EXECUTE_PROCESS(COMMAND "lupdate" "-help" RESULT_VARIABLE LUPDATE_FALLBACK OUTPUT_QUIET) IF(LUPDATE_FALLBACK EQUAL 0) SET(QT_LUPDATE_EXECUTABLE lupdate) SET(QT_LRELEASE_EXECUTABLE lrelease) ELSE() - MESSAGE(FATAL_ERROR "Cannot generate locales") + MESSAGE(WARNING "Cannot generate locales") + RETURN() ENDIF() ENDIF() @@ -26,7 +27,7 @@ FOREACH(_ts_file ${lmms_LOCALES}) STRING(REPLACE ".ts" ".qm" _qm_file "${_ts_file}") STRING(REPLACE ".ts" ".qm" _qm_target "${_ts_target}") ADD_CUSTOM_TARGET(${_ts_target} - COMMAND "${QT_LUPDATE_EXECUTABLE}" -locations none -no-obsolete -I ${CMAKE_SOURCE_DIR}/include/ ${LMMS_SRCS} ${LMMS_INCLUDES} ${LMMS_UIS} `find "\"${CMAKE_SOURCE_DIR}/plugins/\"" -type f -name '*.cpp' -or -name '*.h'` -ts "\"${_ts_file}\"" + COMMAND "${QT_LUPDATE_EXECUTABLE}" -locations none -no-obsolete -I ${CMAKE_SOURCE_DIR}/include/ ${LMMS_SRCS} ${LMMS_UIS} ${CMAKE_SOURCE_DIR}/plugins -ts "\"${_ts_file}\"" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) ADD_CUSTOM_TARGET(${_qm_target} COMMAND "${QT_LRELEASE_EXECUTABLE}" "${_ts_file}" -qm "${_qm_file}" diff --git a/data/locale/cs.ts b/data/locale/cs.ts index f880c4767..6e2435a4d 100644 --- a/data/locale/cs.ts +++ b/data/locale/cs.ts @@ -2,94 +2,112 @@ AboutDialog + About LMMS O LMMS - Version %1 (%2/%3, Qt %4, %5) - Verze %1 (%2/%3, Qt %4, %5) - - - About - O LMMS - - - LMMS - easy music production for everyone - LMMS – snadné vytváření hudby pro každého - - - Authors - Autoři - - - Translation - Překlad - - - Current language not translated (or native English). - -If you're interested in translating LMMS in another language or want to improve existing translations, you're welcome to help us! Simply contact the maintainer! - Michal Janošík - <m164/zavináč/seznam/tečka/cz> - -Chcete-li vylepšit stávající překlad, Vaše pomoc bude vítána! Stačí jen kontaktovat vývojáře! - - - License - Licence - - + LMMS LMMS - Involved - Spolupracovníci + + Version %1 (%2/%3, Qt %4, %5) + Verze %1 (%2/%3, Qt %4, %5) - Contributors ordered by number of commits: - Přispěvovatelé řazeni podle počtu příspěvků: + + About + O LMMS + + LMMS - easy music production for everyone + LMMS – snadné vytváření hudby pro každého + + + Copyright © %1 Copyright © %1 + <html><head/><body><p><a href="https://lmms.io"><span style=" text-decoration: underline; color:#0000ff;">https://lmms.io</span></a></p></body></html> <html><head/><body><p><a href="https://lmms.io"><span style=" text-decoration: underline; color:#0000ff;">https://lmms.io</span></a></p></body></html> + + + Authors + Autoři + + + + Involved + Spolupracovníci + + + + Contributors ordered by number of commits: + Přispěvatelé řazení podle počtu příspěvků: + + + + Translation + Překlad + + + + Current language not translated (or native English). + +If you're interested in translating LMMS in another language or want to improve existing translations, you're welcome to help us! Simply contact the maintainer! + Chcete-li vylepšit stávající překlad, Vaše pomoc bude vítána! Stačí jen kontaktovat vývojáře! + + + + License + Licence + AmplifierControlDialog + VOL HLA + Volume: Hlasitost: + PAN PAN + Panning: Panoráma: + LEFT LEVÝ + Left gain: Zesílení vlevo: + RIGHT PRAVÝ + Right gain: Zesílení vpravo: @@ -97,18 +115,22 @@ Chcete-li vylepšit stávající překlad, Vaše pomoc bude vítána! Stačí je AmplifierControls + Volume Hlasitost + Panning Panoráma + Left gain Zesílení vlevo + Right gain Zesílení vpravo @@ -116,10 +138,12 @@ Chcete-li vylepšit stávající překlad, Vaše pomoc bude vítána! Stačí je AudioAlsaSetupWidget + DEVICE ZAŘÍZENÍ + CHANNELS KANÁLY @@ -127,78 +151,98 @@ Chcete-li vylepšit stávající překlad, Vaše pomoc bude vítána! Stačí je AudioFileProcessorView + Open other sample Otevřít jiný sampl + Click here, if you want to open another audio-file. A dialog will appear where you can select your file. Settings like looping-mode, start and end-points, amplify-value, and so on are not reset. So, it may not sound like the original sample. Klepnutím sem můžete otevřít jiný audio soubor. Zobrazí se dialog, pomocí kterého si soubor můžete vybrat. Nastavení smyčky, počátečního a koncového bodu, zesílení apod. zůstanou nezměněná, takže to nemusí znít jako původní sampl. + Reverse sample Přehrávat pozpátku + If you enable this button, the whole sample is reversed. This is useful for cool effects, e.g. a reversed crash. Zapnete-li toto tlačítko, celý sampl bude přehráván pozpátku. Tato volba je užitečná pro zajímavé efekty jako např. pozpátku přehraná srážka. - Amplify: - Zesílení: - - - With this knob you can set the amplify ratio. When you set a value of 100% your sample isn't changed. Otherwise it will be amplified up or down (your actual sample-file isn't touched!) - Tímto otočným ovladačem můžete nastavit poměr zesílení. Pokud nastavíte hodnotu 100%, sampl se nezmění. Jinak se zesílí nebo ztiší (váš stávající soubor samplu tím nebude nijak ovlivněn!) - - - Startpoint: - Začátek samplu: - - - Endpoint: - Konec samplu: - - - Continue sample playback across notes - Pokračovat v přehrávání samplu při změně noty - - - Enabling this option makes the sample continue playing across different notes - if you change pitch, or the note length stops before the end of the sample, then the next note played will continue where it left off. To reset the playback to the start of the sample, insert a note at the bottom of the keyboard (< 20 Hz) - Povolení této možnosti způsobí, že se sampl bude přehrávat přes různé tóny – když změníte výšku tónu nebo když tón skončí před koncem samplu, bude další přehrávaný tón pokračovat tam, kde přestal. Pro obnovení přehrávání od začátku samplu vložte tón do spodní části klávesnice (< 20 Hz) - - + Disable loop Vypnout smyčku + This button disables looping. The sample plays only once from start to end. Toto tlačítko vypne smyčku. Sampl bude přehrán jen jednou od začátku do konce. + + Enable loop Zapnout smyčku + This button enables forwards-looping. The sample loops between the end point and the loop point. Toto tlačítko zapne smyčku směrem dopředu. Vzorek se bude vracet z koncového bodu na začátek. + This button enables ping-pong-looping. The sample loops backwards and forwards between the end point and the loop point. Toto tlačítko zapne smyčku typu ping-pong. Vzorek bude přehráván dopředu a zpět mezi koncovým bodem a začátkem smyčky. + + Continue sample playback across notes + Pokračovat v přehrávání samplu přes znějící tóny + + + + Enabling this option makes the sample continue playing across different notes - if you change pitch, or the note length stops before the end of the sample, then the next note played will continue where it left off. To reset the playback to the start of the sample, insert a note at the bottom of the keyboard (< 20 Hz) + Povolení této možnosti způsobí, že se sampl bude přehrávat přes různé tóny – když změníte výšku tónu nebo když tón skončí před koncem samplu, bude další přehrávaný tón pokračovat tam, kde přestal. Pro obnovení přehrávání od začátku samplu vložte tón do spodní části klávesnice (< 20 Hz) + + + + Amplify: + Zesílení: + + + + With this knob you can set the amplify ratio. When you set a value of 100% your sample isn't changed. Otherwise it will be amplified up or down (your actual sample-file isn't touched!) + Tímto otočným ovladačem můžete nastavit poměr zesílení. Pokud nastavíte hodnotu 100%, sampl se nezmění. Jinak se zesílí nebo ztiší (váš stávající soubor samplu tím nebude nijak ovlivněn!) + + + + Startpoint: + Začátek samplu: + + + With this knob you can set the point where AudioFileProcessor should begin playing your sample. Tímto otočným ovladačem můžete nastavit bod, od kterého bude AudioFileProcessor přehrávat váš sampl. + + Endpoint: + Konec samplu: + + + With this knob you can set the point where AudioFileProcessor should stop playing your sample. Tímto otočným ovladačem můžete nastavit bod, ve kterém AudioFileProcessor zastaví přehrávání vašeho samplu. + Loopback point: Začátek smyčky: + With this knob you can set the point where the loop starts. Tímto otočným ovladačem můžete nastavit bod, kterým začíná smyčka. @@ -206,6 +250,7 @@ Chcete-li vylepšit stávající překlad, Vaše pomoc bude vítána! Stačí je AudioFileProcessorWaveView + Sample length: Délka samplu: @@ -213,26 +258,32 @@ Chcete-li vylepšit stávající překlad, Vaše pomoc bude vítána! Stačí je AudioJack + JACK client restarted Klient JACK je restartován + LMMS was kicked by JACK for some reason. Therefore the JACK backend of LMMS has been restarted. You will have to make manual connections again. LMMS bylo z nějakého důvodu shozeno JACKem. Proto byl ovladač JACK v LMMS restartován. Musíte znovu provést ruční připojení. + JACK server down JACK server byl zastaven + The JACK server seems to have been shutdown and starting a new instance failed. Therefore LMMS is unable to proceed. You should save your project and restart JACK and LMMS. Vypnutí a nové spuštění serveru JACK se nezdařilo. LMMS proto nemůže pokračovat. Uložte svůj projekt a restartujte JACK i LMMS. + CLIENT-NAME JMÉNO-KLIENTA + CHANNELS KANÁLY @@ -240,10 +291,12 @@ Chcete-li vylepšit stávající překlad, Vaše pomoc bude vítána! Stačí je AudioOss::setupWidget + DEVICE ZAŘÍZENÍ + CHANNELS KANÁLY @@ -251,10 +304,12 @@ Chcete-li vylepšit stávající překlad, Vaše pomoc bude vítána! Stačí je AudioPortAudio::setupWidget + BACKEND OVLADAČ + DEVICE ZAŘÍZENÍ @@ -262,10 +317,12 @@ Chcete-li vylepšit stávající překlad, Vaše pomoc bude vítána! Stačí je AudioPulseAudio::setupWidget + DEVICE ZAŘÍZENÍ + CHANNELS KANÁLY @@ -273,6 +330,7 @@ Chcete-li vylepšit stávající překlad, Vaše pomoc bude vítána! Stačí je AudioSdl::setupWidget + DEVICE ZAŘÍZENÍ @@ -280,10 +338,12 @@ Chcete-li vylepšit stávající překlad, Vaše pomoc bude vítána! Stačí je AudioSndio::setupWidget + DEVICE ZAŘÍZENÍ + CHANNELS KANÁLY @@ -291,10 +351,12 @@ Chcete-li vylepšit stávající překlad, Vaše pomoc bude vítána! Stačí je AudioSoundIo::setupWidget + BACKEND OVLADAČ + DEVICE ZAŘÍZENÍ @@ -302,61 +364,75 @@ Chcete-li vylepšit stávající překlad, Vaše pomoc bude vítána! Stačí je AutomatableModel + &Reset (%1%2) &Resetovat hodnoty (%1%2) + &Copy value (%1%2) &Kopírovat hodnoty (%1%2) + &Paste value (%1%2) &Vložit hodnoty (%1%2) + Edit song-global automation - Upravit automatizaci pro celou skladbu + Upravit hlavní automatizaci skladby + + Remove song-global automation + Odebrat hlavní automatizaci skladby + + + + Remove all linked controls + Odebrat všechny propojené ovládací prvky + + + Connected to %1 Připojeno k %1 + Connected to controller - Připojeno ke kontroléru + Připojeno k ovladači + Edit connection... Upravit připojení... + Remove connection Odebrat připojení + Connect to controller... - Připojit ke kontroléru... - - - Remove song-global automation - Odebrat obecnou automatizaci - - - Remove all linked controls - Odebrat všechny propojené ovládací prvky + Připojit k ovladači... AutomationEditor + Please open an automation pattern with the context menu of a control! - Otevřete prosím automatizační pattern pomocí kontextové nabídky ovládání! + Otevřete prosím automatizační záznam pomocí kontextové nabídky ovládání! + Values copied Hodnoty zkopírovány + All selected values were copied to the clipboard. Všechny označené hodnoty byly zkopírovány do schránky. @@ -364,157 +440,192 @@ Chcete-li vylepšit stávající překlad, Vaše pomoc bude vítána! Stačí je AutomationEditorWindow + Play/pause current pattern (Space) - Přehrát/Pozastavit přehrávání aktuálního patternu (mezerník) + Přehrát/Pozastavit přehrávání aktuálního záznamu (mezerník) + Click here if you want to play the current pattern. This is useful while editing it. The pattern is automatically looped when the end is reached. - Klepněte sem, pokud chcete přehrát aktuální pattern. To je šikovné při editaci, neboť pattern je automaticky přehráván ve smyčce. + Klepněte sem, pokud chcete přehrát aktuální záznam. To je užitečné při editaci. Záznam je automaticky přehráván ve smyčce. + Stop playing of current pattern (Space) - Zastavit přehrávání aktuálního patternu (mezerník) + Zastavit přehrávání aktuálního záznamu (mezerník) + Click here if you want to stop playing of the current pattern. - Klepněte sem, pokud chcete zastavit přehrávání aktuálního patternu. - - - Draw mode (Shift+D) - Režim kreslení (Shift+D) - - - Erase mode (Shift+E) - Režim mazání (Shift+E) - - - Flip vertically - Převrátit vertikálně - - - Flip horizontally - Převrátit horizontálně - - - Click here and the pattern will be inverted.The points are flipped in the y direction. - Klepněte sem, pokud chcete převrátit pattern. Body budou převráceny v ose y. - - - Click here and the pattern will be reversed. The points are flipped in the x direction. - Klepněte sem, pokud chcete převrátit pattern. Body budou převráceny v ose x. - - - Click here and draw-mode will be activated. In this mode you can add and move single values. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. - Klepněte sem, pokud chcete aktivovat režim kreslení. V tomto výchozím a nejčastěji užívaném režimu lze přidávat a přesunovat jednotlivé hodnoty. Pro aktivaci můžete využít též klávesové zkratky "Shift+D". - - - Click here and erase-mode will be activated. In this mode you can erase single values. You can also press 'Shift+E' on your keyboard to activate this mode. - Klepněte sem, pokud chcete aktivovat režim mazání. V tomto režimu lze mazat jednotlivé hodnoty. Pro aktivaci můžete využít též klávesové zkratky "Shift+E". - - - Discrete progression - Terasovitý průběh - - - Linear progression - Lineární průběh - - - Cubic Hermite progression - Křivkovitý průběh - - - Tension value for spline - Hodnota napětí pro křivku - - - A higher tension value may make a smoother curve but overshoot some values. A low tension value will cause the slope of the curve to level off at each control point. - Vyšší hodnota napětí vytvoří hladší křivku, ale více se vzdálí od zadaných hodnot. Nižší hodnota napětí upřednostní výchozí sklon křivky v každém kontrolním bodě. - - - Click here to choose discrete progressions for this automation pattern. The value of the connected object will remain constant between control points and be set immediately to the new value when each control point is reached. - Klepnutím sem vyberete terasovitý vývoj pro tento automatizační pattern. Hodnota připojeného objektu zůstane konstantní mezi ovládacími body a okamžitě nastavena na novou hodnotu, když se dosáhne dalšího ovládacího bodu. - - - Click here to choose linear progressions for this automation pattern. The value of the connected object will change at a steady rate over time between control points to reach the correct value at each control point without a sudden change. - Klepnutím sem vyberete lineární vývoj pro tento automatizační pattern. Hodnota připojeného objektu bude mezi ovládacími body měněna přímočaře, aby postupně došlo k dosažení dalšího kontrolního bodu. - - - Click here to choose cubic hermite progressions for this automation pattern. The value of the connected object will change in a smooth curve and ease in to the peaks and valleys. - Klepnutím sem vyberte vývoj typu cubic hermite pro tento automatizační pattern. Hodnota připojeného objektu se změní po plynulé křivce a lehce přejde do vrchních a spodních bodů. - - - Cut selected values (%1+X) - Vyjmout označené hodnoty (%1+X) - - - Copy selected values (%1+C) - Kopírovat označené hodnoty (%1+C) - - - Paste values from clipboard (%1+V) - Vložit hodnoty ze schránky (%1+V) - - - Click here and selected values will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. - Klepněte sem, pokud chcete označené hodnoty vyjmout a uložit do schránky. Vložit je pak můžete kdekoliv v libovolném patternu pomocí tlačítka Vložit. - - - Click here and selected values will be copied into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. - Klepněte sem, pokud chcete označené hodnoty zkopírovat do schránky. Vložit je pak můžete kdekoliv v libovolného patternu pomocí tlačítka Vložit. - - - Click here and the values from the clipboard will be pasted at the first visible measure. - Klepnete-li sem, budou hodnoty ze schránky vloženy do prvního viditelného taktu. - - - Tension: - Napětí: - - - Automation Editor - no pattern - Editor automatizace – žádný pattern - - - Automation Editor - %1 - Editor automatizace – %1 + Klepněte sem, pokud chcete zastavit přehrávání aktuálního záznamu. + Edit actions Akce úprav + + Draw mode (Shift+D) + Režim kreslení (Shift+D) + + + + Erase mode (Shift+E) + Režim mazání (Shift+E) + + + + Flip vertically + Převrátit vertikálně + + + + Flip horizontally + Převrátit horizontálně + + + + Click here and the pattern will be inverted.The points are flipped in the y direction. + Klepněte sem, pokud chcete převrátit záznam. Body budou převráceny v ose y. + + + + Click here and the pattern will be reversed. The points are flipped in the x direction. + Klepněte sem, pokud chcete převrátit záznam. Body budou převráceny v ose x. + + + + Click here and draw-mode will be activated. In this mode you can add and move single values. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. + Klepněte sem, pokud chcete aktivovat režim kreslení. V tomto výchozím a nejčastěji užívaném režimu lze přidávat a přesunovat jednotlivé hodnoty. Pro aktivaci můžete využít též klávesové zkratky "Shift+D". + + + + Click here and erase-mode will be activated. In this mode you can erase single values. You can also press 'Shift+E' on your keyboard to activate this mode. + Klepněte sem, pokud chcete aktivovat režim mazání. V tomto režimu lze mazat jednotlivé hodnoty. Pro aktivaci můžete využít též klávesové zkratky "Shift+E". + + + Interpolation controls Ovládání interpolace - Timeline controls - Ovládání časové osy + + Discrete progression + Terasovitý průběh + + Linear progression + Lineární průběh + + + + Cubic Hermite progression + Křivkovitý průběh + + + + Tension value for spline + Hodnota napětí pro křivku + + + + A higher tension value may make a smoother curve but overshoot some values. A low tension value will cause the slope of the curve to level off at each control point. + Vyšší hodnota napětí vytvoří hladší křivku, ale více se vzdálí od zadaných hodnot. Nižší hodnota napětí upřednostní výchozí sklon křivky v každém kontrolním bodě. + + + + Click here to choose discrete progressions for this automation pattern. The value of the connected object will remain constant between control points and be set immediately to the new value when each control point is reached. + Klepnutím sem vyberete terasovitý vývoj pro tento automatizační záznam. Hodnota připojeného objektu zůstane neměnná mezi ovládacími body a okamžitě bude nastavena na novou hodnotu, když se dosáhne dalšího ovládacího bodu. + + + + Click here to choose linear progressions for this automation pattern. The value of the connected object will change at a steady rate over time between control points to reach the correct value at each control point without a sudden change. + Klepnutím sem vyberete lineární vývoj pro tento automatizační záznam. Hodnota připojeného objektu bude mezi ovládacími body měněna přímočaře, aby postupně došlo k dosažení dalšího kontrolního bodu. + + + + Click here to choose cubic hermite progressions for this automation pattern. The value of the connected object will change in a smooth curve and ease in to the peaks and valleys. + Klepnutím sem vyberte vývoj typu cubic hermite pro tento automatizační záznam. Hodnota připojeného objektu se změní po plynulé křivce a hladce přejde do vrchních i spodních bodů. + + + + Tension: + Napětí: + + + + Cut selected values (%1+X) + Vyjmout označené hodnoty (%1+X) + + + + Copy selected values (%1+C) + Kopírovat označené hodnoty (%1+C) + + + + Paste values from clipboard (%1+V) + Vložit hodnoty ze schránky (%1+V) + + + + Click here and selected values will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. + Klepněte sem, pokud chcete označené hodnoty vyjmout a uložit do schránky. Vložit je pak můžete kdekoliv v libovolném záznamu pomocí tlačítka Vložit. + + + + Click here and selected values will be copied into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. + Klepněte sem, pokud chcete označené hodnoty zkopírovat do schránky. Vložit je pak můžete kdekoliv v libovolném záznamu pomocí tlačítka Vložit. + + + + Click here and the values from the clipboard will be pasted at the first visible measure. + Klepnete-li sem, budou hodnoty ze schránky vloženy do prvního viditelného taktu. + + + Zoom controls Ovládání zvětšení + Quantization controls Ovládání kvantizace - Model is already connected to this pattern. - Model je již k tomuto patternu připojen. - - + Quantization Kvantizace + Quantization. Sets the smallest step size for the Automation Point. By default this also sets the length, clearing out other points in the range. Press <Ctrl> to override this behaviour. Kvantizace. Nastaví nejmenší velikost kroku pro body automatizace. Ve výchozím stavu také nastaví délku a vymazává další body v rozsahu. Stisknutím <Ctrl> zrušíte toto chování. + + + + Automation Editor - no pattern + Editor automatizace – žádný záznam + + + + + Automation Editor - %1 + Editor automatizace – %1 + + + + Model is already connected to this pattern. + Model je již k tomuto záznamu připojen. + AutomationPattern + Drag a control while pressing <%1> Ovládací prvek táhni při stisknutém <%1> @@ -522,49 +633,65 @@ Chcete-li vylepšit stávající překlad, Vaše pomoc bude vítána! Stačí je AutomationPatternView + + double-click to open this pattern in automation editor + dvojklikem otevřít tento pattern v Editoru automatizace + + + Open in Automation editor Otevřít v Editoru automatizace + Clear Vyčistit + Reset name Obnovit výchozí jméno + Change name Změnit jméno - %1 Connections - %1 Připojení - - - Disconnect "%1" - Odpojit "%1" - - + Set/clear record Zapnout/Vypnout záznam + Flip Vertically (Visible) Převrátit vertikálně (viditelné) + Flip Horizontally (Visible) Převrátit horizontálně (viditelné) + + %1 Connections + %1 Připojení + + + + Disconnect "%1" + Odpojit "%1" + + + Model is already connected to this pattern. - Model je již k tomuto patternu připojen. + Model je již k tomuto záznamu připojen. AutomationTrack + Automation track Stopa automatizace @@ -572,77 +699,95 @@ Chcete-li vylepšit stávající překlad, Vaše pomoc bude vítána! Stačí je BBEditor + Beat+Bassline Editor Editor bicích/basů + Play/pause current beat/bassline (Space) - Přehrát/Pozastavit přehrávání aktuálního patternu bicích/basů (mezerník) + Přehrát/Pozastavit přehrávání aktuálního záznamu bicích/basů (mezerník) + Stop playback of current beat/bassline (Space) - Zastavit přehrávání aktuálního patternu bicích/basů (mezerník) + Zastavit přehrávání aktuálního záznamu bicích/basů (mezerník) + Click here to play the current beat/bassline. The beat/bassline is automatically looped when its end is reached. - Klepněte sem, pokud chcete přehrát aktuální pattern bicích/basů. Bicí/basy jsou automaticky přehrávány ve smyčce. + Klepněte sem, pokud chcete přehrát aktuální záznam bicích/basů. Bicí/basy jsou automaticky přehrávány ve smyčce. + Click here to stop playing of current beat/bassline. - Klepněte sem, pokud chcete zastavit přehrávání aktuálního patternu bicích/basů. - - - Add beat/bassline - Přidat bicí/basy - - - Add automation-track - Přidat stopu automatizace - - - Remove steps - Odstranit kroky - - - Add steps - Přidat kroky + Klepněte sem, pokud chcete zastavit přehrávání aktuálního záznamu bicích/basů. + Beat selector Výběr rytmu + Track and step actions Akce stopy a kroků - Clone Steps - Klonovat kroky + + Add beat/bassline + Přidat bicí/basy + Add sample-track + Přidat stopu samplů + + + + Add automation-track Přidat stopu automatizace + + + Remove steps + Odstranit kroky + + + + Add steps + Přidat kroky + + + + Clone Steps + Klonovat kroky + BBTCOView + Open in Beat+Bassline-Editor Otevřít v editoru bicích/basů + Reset name Resetovat jméno + Change name Změnit jméno + Change color Změnit barvu + Reset color to default Obnovit výchozí barvy @@ -650,10 +795,12 @@ Chcete-li vylepšit stávající překlad, Vaše pomoc bude vítána! Stačí je BBTrack + Beat/Bassline %1 Bicí/basy %1 + Clone of %1 Klon z %1 @@ -661,26 +808,32 @@ Chcete-li vylepšit stávající překlad, Vaše pomoc bude vítána! Stačí je BassBoosterControlDialog + FREQ FREKV + Frequency: Frekvence: + GAIN ZES + Gain: Zesílení: + RATIO POMĚR + Ratio: Poměr: @@ -688,14 +841,17 @@ Chcete-li vylepšit stávající překlad, Vaše pomoc bude vítána! Stačí je BassBoosterControls + Frequency Frekvence + Gain Zesílení + Ratio Poměr @@ -703,89 +859,111 @@ Chcete-li vylepšit stávající překlad, Vaše pomoc bude vítána! Stačí je BitcrushControlDialog + IN IN + OUT OUT + + GAIN ZISK + Input Gain: Zesílení vstupu: - Input Noise: - Vstup šumu: - - - Output Gain: - Zesílení výstupu: - - - CLIP - OŘÍZ - - - Output Clip: - Oříznutí výstupu: - - - Rate Enabled - Frekvence zapnuta - - - Enable samplerate-crushing - Zapnout drtič vzorkovací frekvence - - - Depth Enabled - Hloubka zapnuta - - - Enable bitdepth-crushing - Zapnout drtič bitové hloubky - - - Sample rate: - Vzorkovací frekvence: - - - Stereo difference: - Stereo rozdíl: - - - Levels: - Úrovně: - - + NOISE ŠUM + + Input Noise: + Vstup šumu: + + + + Output Gain: + Zesílení výstupu: + + + + CLIP + OŘÍZ + + + + Output Clip: + Oříznutí výstupu: + + + + Rate Enabled + Frekvence zapnuta + + + + Enable samplerate-crushing + Zapnout drtič vzorkovací frekvence + + + + Depth Enabled + Hloubka zapnuta + + + + Enable bitdepth-crushing + Zapnout drtič bitové hloubky + + + FREQ FREKV + + Sample rate: + Vzorkovací frekvence: + + + STEREO STEREO + + Stereo difference: + Stereo rozdíl: + + + QUANT KVANT + + + Levels: + Úrovně: + CaptionMenu + &Help &Nápověda + Help (not available) Nápověda (nedostupná) @@ -793,10 +971,12 @@ Chcete-li vylepšit stávající překlad, Vaše pomoc bude vítána! Stačí je CarlaInstrumentView + Show GUI Ukázar grafické rozhraní + Click here to show or hide the graphical user interface (GUI) of Carla. Klepněte sem pro zobrazení nebo skrytí grafického uživatelského rozhraní (GUI) Carla. @@ -804,65 +984,81 @@ Chcete-li vylepšit stávající překlad, Vaše pomoc bude vítána! Stačí je Controller + Controller %1 - Kontrolér %1 + Ovladač %1 ControllerConnectionDialog + Connection Settings Nastavení připojení + MIDI CONTROLLER - MIDI KONTROLÉR + MIDI OVLADAČ + Input channel Vstupní kanál + CHANNEL KANÁL + Input controller - Vstupní kontrolér + Vstupní ovladač + CONTROLLER - KONTROLÉR + OVLADAČ + + Auto Detect Autodetekce + MIDI-devices to receive MIDI-events from MIDI zařízení k přijmu MIDI události + USER CONTROLLER - UŽIVATELSKÝ KONTROLÉR + UŽIVATELSKÝ OVLADAČ + MAPPING FUNCTION MAPOVACÍ FUNKCE + OK OK + Cancel Zrušit + LMMS LMMS + Cycle Detected. Zjištěno zacyklení. @@ -870,18 +1066,22 @@ Chcete-li vylepšit stávající překlad, Vaše pomoc bude vítána! Stačí je ControllerRackView + Controller Rack - Kontroléry + Ovladače + Add Přidat + Confirm Delete Potvrdit smazání + Confirm delete? There are existing connection(s) associated with this controller. There is no way to undo. Opravdu smazat? Je (jsou) zde propojení na tento ovladač. Nebude možné vrátit se zpět. @@ -889,93 +1089,115 @@ Chcete-li vylepšit stávající překlad, Vaše pomoc bude vítána! Stačí je ControllerView + Controls Ovládací prvky + Controllers are able to automate the value of a knob, slider, and other controls. Kontroléry jsou schopny automatizovat nastavení otočných ovladačů, táhel a dalších řídicích prvků. + Rename controller - Přejmenovat kontrolér + Přejmenovat ovladač + Enter the new name for this controller - Vložte nové jméno pro tento kontrolér - - - &Remove this controller - Odst&ranit tento kontrolér - - - Re&name this controller - Přejme&novat tento kontrolér + Vložte nové jméno pro tento ovladač + LFO LFO + + + &Remove this controller + Odst&ranit tento ovladač + + + + Re&name this controller + Přejme&novat tento ovladač + CrossoverEQControlDialog + Band 1/2 Crossover: Přechod mezi pásmy 1/2: + Band 2/3 Crossover: Přechod mezi pásmy 2/3: + Band 3/4 Crossover: Přechod mezi pásmy 3/4: + Band 1 Gain: Zesílení pásma 1: + Band 2 Gain: Zesílení pásma 2: + Band 3 Gain: Zesílení pásma 3: + Band 4 Gain: Zesílení pásma 4: + Band 1 Mute Ztlumení pásma 1 + Mute Band 1 Ztlumit pásmo 1 + Band 2 Mute Ztlumení pásma 2 + Mute Band 2 Ztlumit pásmo 2 + Band 3 Mute Ztlumení pásma 3 + Mute Band 3 Ztlumit pásmo 3 + Band 4 Mute Ztlumení pásma 4 + Mute Band 4 Ztlumit pásmo 4 @@ -983,22 +1205,27 @@ Chcete-li vylepšit stávající překlad, Vaše pomoc bude vítána! Stačí je DelayControls + Delay Samples Zpoždění vzorků + Feedback Zpětná vazba + Lfo Frequency Frekvence LFO + Lfo Amount Hloubka LFO + Output gain Zesílení výstupu @@ -1006,228 +1233,311 @@ Chcete-li vylepšit stávající překlad, Vaše pomoc bude vítána! Stačí je DelayControlsDialog - Lfo Amt - Hloubka LFO - - - Delay Time - Délka zpoždění - - - Feedback Amount - Hloubka zpětné vazby - - - Lfo - LFO - - - Out Gain - Zesílení výstupu - - - Gain - Zesílení - - + DELAY ZPOŽ + + Delay Time + Délka zpoždění + + + FDBK ZPVAZ + + Feedback Amount + Hloubka zpětné vazby + + + RATE RYCH + + Lfo + LFO + + + AMNT MNOŽ + + + Lfo Amt + Hloubka LFO + + + + Out Gain + Zesílení výstupu + + + + Gain + Zesílení + DualFilterControlDialog - Filter 1 enabled - Filtr 1 zapnutý - - - Filter 2 enabled - Filtr 2 zapnutý - - - Click to enable/disable Filter 1 - Klepněte pro zapnutí/vypnutí filtru 1 - - - Click to enable/disable Filter 2 - Klepněte pro zapnutí/vypnutí filtru 2 - - + + FREQ FREKV + + Cutoff frequency Frekvence oříznutí + + RESO REZON + + Resonance Rezonance + + GAIN ZESIL + + Gain Zesílení + MIX POMĚR + Mix Poměr + + + Filter 1 enabled + Filtr 1 zapnutý + + + + Filter 2 enabled + Filtr 2 zapnutý + + + + Click to enable/disable Filter 1 + Klepněte pro zapnutí/vypnutí filtru 1 + + + + Click to enable/disable Filter 2 + Klepněte pro zapnutí/vypnutí filtru 2 + DualFilterControls + Filter 1 enabled Filtr 1 zapnutý + Filter 1 type Typ filtru 1 + Cutoff 1 frequency Frekvence oříznutí 1 + Q/Resonance 1 Q/rezonance 1 + Gain 1 Zesílení 1 + Mix Mix + Filter 2 enabled Filtr 1 zapnutý + Filter 2 type Typ filtru 2 + Cutoff 2 frequency Frekvence oříznutí 2 + Q/Resonance 2 Q/rezonance 2 + Gain 2 Zesílení 2 + + LowPass Dolní propust + + HiPass Horní propust + + BandPass csg Pásmová propust csg + + BandPass czpg Pásmová propust czpg + + Notch Pásmová zádrž + + Allpass Všepásmový filtr + + Moog Moogův filtr + + 2x LowPass 2x dolní propust + + RC LowPass 12dB RC dolní propust 12dB + + RC BandPass 12dB RC pásmová propust 12dB + + RC HighPass 12dB RC horní propust 12dB + + RC LowPass 24dB RC dolní propust 24dB + + RC BandPass 24dB RC pásmová propust 24dB + + RC HighPass 24dB RC horní propust 24dB + + Vocal Formant Filter Vokální formantový filtr + + 2x Moog 2x Moogův filtr + + SV LowPass SV dolní propust + + SV BandPass SV pásmová propust + + SV HighPass SV horní propust + + SV Notch SV pásmová zádrž + + Fast Formant Rychlý formantový filtr + + Tripole Třípólový filtr @@ -1235,48 +1545,58 @@ Chcete-li vylepšit stávající překlad, Vaše pomoc bude vítána! Stačí je Editor + + Transport controls + Řízení přenosu + + + Play (Space) Přehrát (mezerník) + Stop (Space) Zastavit (mezerník) + Record Nahrávat + Record while playing Nahrávat při přehrávání - - Transport controls - Řízení přenosu - Effect + Effect enabled Efekt aktivován + Wet/Dry mix Poměr zpracovaného/původního signálu + Gate Brána + Decay - Útlum + Pokles EffectChain + Effects enabled Efekty aktivovány @@ -1284,10 +1604,12 @@ Chcete-li vylepšit stávající překlad, Vaše pomoc bude vítána! Stačí je EffectRackView + EFFECTS CHAIN ŘETĚZ EFEKTŮ + Add effect Přidat efekt @@ -1295,22 +1617,28 @@ Chcete-li vylepšit stávající překlad, Vaše pomoc bude vítána! Stačí je EffectSelectDialog + Add effect Přidat efekt + + Name Název + Type Typ + Description Popis + Author Autor @@ -1318,54 +1646,67 @@ Chcete-li vylepšit stávající překlad, Vaše pomoc bude vítána! Stačí je EffectView + Toggles the effect on or off. Zapnout nebo vypnout efekty. + On/Off Zap/Vyp + W/D POM + Wet Level: Úroveň zpracovaného signálu: + The Wet/Dry knob sets the ratio between the input signal and the effect signal that forms the output. Otočný ovladač Poměr nastavuje poměr mezi vstupním signálem a signálem efektu, který formuje výstup. + DECAY - ÚTLUM + POKLES + Time: Délka: + The Decay knob controls how many buffers of silence must pass before the plugin stops processing. Smaller values will reduce the CPU overhead but run the risk of clipping the tail on delay and reverb effects. Otočný ovladač Útlum nastavuje, kolik bufferů ticha musí proběhnout před tím, než plugin přestane zpracovávat. Menší hodnoty zredukují přetížení CPU, ale mohou způsobit oříznutí na konci zpožďovacích a dozvukových efektů. + GATE BRÁ + Gate: Brána: + The Gate knob controls the signal level that is considered to be 'silence' while deciding when to stop processing signals. Otočný ovladač Brána určuje sílu signálu, který je považován za "ticho" při rozhodování, kdy skončit se zpracováním signálů. + Controls Ovladače + Effect plugins function as a chained series of effects where the signal will be processed from top to bottom. The On/Off switch allows you to bypass a given plugin at any point in time. @@ -1395,14 +1736,17 @@ Tlačítko Ovladače otevře dialogové okno pro úpravu parametrů efektu. Klepnutí pravým tlačítkem myši vyvolá kontextovou nabídku, kde můžete měnit pořadí, ve kterém budou efekty zpracovávány, nebo můžete efekt úplně odstranit. + Move &up Posunout &nahoru + Move &down Posunout &dolů + &Remove this plugin &Odstranit tento plugin @@ -1410,58 +1754,72 @@ Klepnutí pravým tlačítkem myši vyvolá kontextovou nabídku, kde můžete m EnvelopeAndLfoParameters + Predelay Předzpoždění + Attack Náběh + Hold Držení + Decay Útlum + Sustain Vydržení + Release - Uvolnění + Doznění + Modulation Modulace + LFO Predelay Předzpoždění LFO + LFO Attack Náběh LFO + LFO speed Rychlost LFO + LFO Modulation Modulace LFO + LFO Wave Shape Tvar vlny LFO + Freq x 100 Frekvence x 100 + Modulate Env-Amount Hloubka modulace @@ -1469,349 +1827,439 @@ Klepnutí pravým tlačítkem myši vyvolá kontextovou nabídku, kde můžete m EnvelopeAndLfoView + + DEL PŘED + Predelay: Předzpoždění: + Use this knob for setting predelay of the current envelope. The bigger this value the longer the time before start of actual envelope. Tento otočný ovladač nastavuje předzpoždění (predelay) aktuální obálky. Zvýšením hodnoty se prodlouží čas před začátkem obálky. + + ATT NÁB + Attack: Náběh: + Use this knob for setting attack-time of the current envelope. The bigger this value the longer the envelope needs to increase to attack-level. Choose a small value for instruments like pianos and a big value for strings. Tento otočný ovladač nastavuje náběh (attack) u aktuální obálky. Zvýšením hodnoty se prodlouží délka náběhu obálky. Zvolte nižší hodnotu pro nástroje typu piano a vyšší pro smyčce. + HOLD DRŽ + Hold: Držení: + Use this knob for setting hold-time of the current envelope. The bigger this value the longer the envelope holds attack-level before it begins to decrease to sustain-level. Tento otočný ovladač nastavuje délku držení (hold) u aktuální obálky. Zvýšením hodnoty se prodlouží část obálky, která zůstává na úrovni náběhu (attack) ještě před začátkem útlumu (decay) na úroveň vydržení (sustain). + DEC ÚTL + Decay: Útlum: + Use this knob for setting decay-time of the current envelope. The bigger this value the longer the envelope needs to decrease from attack-level to sustain-level. Choose a small value for instruments like pianos. Tento otočný ovladač nastavuje délku útlumu (decay) u aktuální obálky. Zvýšením hodnoty se prodlouží část obálky, potřebná k zeslabení z úrovně náběhu (attack) na úroveň vydržení (sustain). Zvolte nižší hodnotu pro nástroje typu piano. + SUST VYD + Sustain: - Vydržení: + Držení: + Use this knob for setting sustain-level of the current envelope. The bigger this value the higher the level on which the envelope stays before going down to zero. Tento otočný ovladač nastavuje vydržení (sustain) u aktuální obálky. Zvýšením hodnoty se navýší úroveň, na které obálka zůstává před poklesem na nulu. + REL UVOL + Release: Uvolnění: + Use this knob for setting release-time of the current envelope. The bigger this value the longer the envelope needs to decrease from sustain-level to zero. Choose a big value for soft instruments like strings. Tento otočný ovladač nastavuje délku uvolnění (release) u aktuální obálky. Zvýšením hodnoty se prodlouží část obálky, potřebná k zeslabení z úrovně vydržení (sustain) na nulovou úroveň. Zvolte vyšší hodnotu pro nástroje s měkkým zvukem, jako např. smyčce. + + AMT MOD + + Modulation amount: Hloubka modulace: + Use this knob for setting modulation amount of the current envelope. The bigger this value the more the according size (e.g. volume or cutoff-frequency) will be influenced by this envelope. Tento otočný ovladač nastavuje hloubku modulace u aktuální obálky. Zvýšení této hodnoty v závislosti na velikosti (např. hlasitosti nebo frekvence odstřihnutí) způsobí větší ovlivnění touto obálkou. + LFO predelay: Předzpoždění LFO: + Use this knob for setting predelay-time of the current LFO. The bigger this value the the time until the LFO starts to oscillate. Tento otočný ovladač nastavuje délku předzpoždění (predelay) aktuálního LFO. Zvýšením hodnoty se prodlouží čas před spuštěním kmitání LFO. + LFO- attack: Náběh LFO: + Use this knob for setting attack-time of the current LFO. The bigger this value the longer the LFO needs to increase its amplitude to maximum. Tento otočný ovladač nastavuje délku náběhu (attack) u aktuálního LFO. Zvýšením hodnoty se prodlouží čas potřebný pro zvýšení amplitudy LFO na maximum. + SPD RYCH + LFO speed: Rychlost LFO: + Use this knob for setting speed of the current LFO. The bigger this value the faster the LFO oscillates and the faster will be your effect. Tento otočný ovladač nastavuje rychlost u aktuálního LFO. Zvýšením hodnoty se zrychlí kmitání LFO a průběh vašeho efektu. + Use this knob for setting modulation amount of the current LFO. The bigger this value the more the selected size (e.g. volume or cutoff-frequency) will be influenced by this LFO. Tento otočný ovladač nastavuje hloubku modulace u aktuálního LFO. Zvýšení hodnoty v závislosti na velikosti (např. hlasitosti nebo frekvence odstřihnutí) způsobí větší ovlivnění tímto LFO. + Click here for a sine-wave. Klepněte sem pro sinusovou vlnu. + Click here for a triangle-wave. Klepněte sem pro trojúhelníkovou vlnu. + Click here for a saw-wave for current. Klepněte sem pro pilovitou vlnu. + Click here for a square-wave. Klepněte sem pro pravoúhlou vlnu. + Click here for a user-defined wave. Afterwards, drag an according sample-file onto the LFO graph. Klepněte sem pro vlastní vlnu. Poté přetáhněte zvolený soubor samplu do grafického okna LFO. + + Click here for random wave. + Klepněte sem pro náhodnou vlnu. + + + FREQ x 100 FREKVENCE x 100 + Click here if the frequency of this LFO should be multiplied by 100. Klepněte sem, pokud má být frekvence LFO vynásobena x100. + multiply LFO-frequency by 100 vynásobit frekvenci LFO x100 + MODULATE ENV-AMOUNT MODULOVAT OBÁLKU + Click here to make the envelope-amount controlled by this LFO. Klepněte sem, pokud má být množství obálky řízeno tímto LFO. + control envelope-amount by this LFO řízení množství obálky tímto LFO + ms/LFO: ms/LFO: + Hint Rada + Drag a sample from somewhere and drop it in this window. Sampl odněkud přetáhněte a pusťte jej v tomto okně. - - Click here for random wave. - Klepněte sem pro náhodnou vlnu. - EqControls + Input gain Zesílení vstupu + Output gain Zesílení výstupu + Low shelf gain Zesílení dolního šelfu + Peak 1 gain Zesílení špičky 1 + Peak 2 gain Zesílení špičky 2 + Peak 3 gain Zesílení špičky 3 + Peak 4 gain Zesílení špičky 4 + High Shelf gain Zesílení horního šelfu + HP res Rezonance horní propusti + Low Shelf res Rezonance dolního šelfu + Peak 1 BW Šířka pásma špičky 1 + Peak 2 BW Šířka pásma špičky 2 + Peak 3 BW Šířka pásma špičky 3 + Peak 4 BW Šířka pásma špičky 4 + High Shelf res Rezonance horního šelfu + LP res Rezonance dolní propusti + HP freq Frekvence horní propusti + Low Shelf freq Frekvence dolního šelfu + Peak 1 freq Frekvence špičky 1 + Peak 2 freq Frekvence špičky 2 + Peak 3 freq Frekvence špičky 3 + Peak 4 freq Frekvence špičky 3 + High shelf freq Frekvence špičky 4 + LP freq Frekvence dolní propusti + HP active Horní propust aktivní + Low shelf active Dolní šelf aktivní + Peak 1 active Špička 1 aktivní + Peak 2 active Špička 2 aktivní + Peak 3 active Špička 3 aktivní + Peak 4 active Špička 4 aktivní + High shelf active Horní šelf aktivní + LP active Dolní propust aktivní + LP 12 DP 12 + LP 24 DP 24 + LP 48 DP 48 + HP 12 HP 12 + HP 24 HP 24 + HP 48 HP 48 + low pass type typ dolní propusti + high pass type typ horní propusti + Analyse IN Analýza VSTUPU + Analyse OUT Analýza VÝSTUPU @@ -1819,85 +2267,108 @@ Klepnutí pravým tlačítkem myši vyvolá kontextovou nabídku, kde můžete m EqControlsDialog + HP HP + Low Shelf Dolní šelf + Peak 1 Špička 1 + Peak 2 Špička 2 + Peak 3 Špička 3 + Peak 4 Špička 4 + High Shelf Horní šelf + LP DP + In Gain Zesílení vstupu + + + Gain Zesílení + Out Gain Zesílení výstupu + Bandwidth: Šířka pásma: + + Octave + oktávy + + + Resonance : Rezonance: + Frequency: Frekvence: + lp grp dp skup + hp grp hp skup - - Octave - oktávy - EqHandle + Reso: Rezon: + BW: ŠPás: + + Freq: Frekv: @@ -1905,190 +2376,236 @@ Klepnutí pravým tlačítkem myši vyvolá kontextovou nabídku, kde můžete m ExportProjectDialog + Export project Exportovat projekt + Output Výstup + File format: Formát souboru: + Samplerate: Vzorkovací frekvence: + 44100 Hz 44100 Hz + 48000 Hz 48000 Hz + 88200 Hz 88200 Hz + 96000 Hz 96000 Hz + 192000 Hz 192000 Hz - Bitrate: - Datový tok: - - - 64 KBit/s - 64 kbit/s - - - 128 KBit/s - 128 kbit/s - - - 160 KBit/s - 160 kbit/s - - - 192 KBit/s - 192 kbit/s - - - 256 KBit/s - 256 kbit/s - - - 320 KBit/s - 320 kbit/s - - + Depth: Hloubka: + 16 Bit Integer 16 bitů celočíselně + + 24 Bit Integer + 24 bitů celočíselně + + + 32 Bit Float 32 bitů s plovoucí čárkou + + Stereo mode: + Režim stereo: + + + + Stereo + Stereo + + + + Joint Stereo + Joint stereo + + + + Mono + Mono + + + + Bitrate: + Datový tok: + + + + 64 KBit/s + 64 kbit/s + + + + 128 KBit/s + 128 kbit/s + + + + 160 KBit/s + 160 kbit/s + + + + 192 KBit/s + 192 kbit/s + + + + 256 KBit/s + 256 kbit/s + + + + 320 KBit/s + 320 kbit/s + + + + Use variable bitrate + Použít proměnlivý datový tok + + + Quality settings Nastavení kvality + Interpolation: Interpolace: + Zero Order Hold Zero-order hold + Sinc Fastest Sinc nejrychlejší + Sinc Medium (recommended) Sinc střední (doporučeno) + Sinc Best (very slow!) Sinc nejlepší (velmi pomalé!) + Oversampling (use with care!): Převzorkování (používejte opatrně!): + 1x (None) 1x (žádné) + 2x 2x + 4x 4x + 8x 8x - Start - Začít - - - Cancel - Zrušit - - + Export as loop (remove end silence) Exportovat jako smyčku (odstranění ticha na konci) + Export between loop markers Exportovat obsah smyčky + + Start + Začít + + + + Cancel + Zrušit + + + Could not open file Nemohu otevřít soubor - Export project to %1 - Exportovat projekt do %1 - - - Error - Chyba - - - Error while determining file-encoder device. Please try to choose a different output format. - Chyba při zjišťování souboru enkodéru. Zkuste prosím vybrat jiný výstupní formát. - - - Rendering: %1% - Renderuji: %1% - - + Could not open file %1 for writing. Please make sure you have write permission to the file and the directory containing the file and try again! Nelze otevřít soubor %1 pro zápis. Ověřte si prosím, zda máte povolen zápis do souboru a do složky, ve které je umístěn, a zkuste znovu! - 24 Bit Integer - 24 bitů celočíselně + + Export project to %1 + Exportovat projekt do %1 - Use variable bitrate - Použít proměnlivý datový tok + + Error + Chyba - Stereo mode: - Režim stereo: + + Error while determining file-encoder device. Please try to choose a different output format. + Chyba při zjišťování souboru enkodéru. Zkuste prosím vybrat jiný výstupní formát. - Stereo - Stereo - - - Joint Stereo - Joint stereo - - - Mono - Mono + + Rendering: %1% + Renderuji: %1% Compression level: @@ -2153,6 +2670,8 @@ Ověřte si prosím, zda máte povolen zápis do souboru a do složky, ve které Fader + + Please enter a new value between %1 and %2: Vložte prosím novou hodnotu mezi %1 a %2: @@ -2160,6 +2679,7 @@ Ověřte si prosím, zda máte povolen zápis do souboru a do složky, ve které FileBrowser + Browser Prohlížeč @@ -2175,65 +2695,83 @@ Ověřte si prosím, zda máte povolen zápis do souboru a do složky, ve které FileBrowserTreeWidget + Send to active instrument-track Odeslat do aktivní stopy nástroje - Open in new instrument-track/B+B Editor - Otevřít v nové nástrojové stopě / editoru bicich/basů - - - Loading sample - Načítám vzorek - - - Please wait, loading sample for preview... - Počkejte prosím, načítám vzorek pro náhled... - - - --- Factory files --- - --- Tovární soubory --- - - + Open in new instrument-track/Song Editor Otevřít v nové nástrojové stopě / Editoru skladby + + Open in new instrument-track/B+B Editor + Otevřít v nové nástrojové stopě / editoru bicich/basů + + + + Loading sample + Načítám vzorek + + + + Please wait, loading sample for preview... + Počkejte prosím, načítám vzorek pro náhled... + + + Error Chyba + does not appear to be a valid nevypadá, že je platný + file soubor + + + --- Factory files --- + --- Tovární soubory --- + + + + FileBrowserTreeWidget FlangerControls + Delay Samples Zpoždění vzorků + Lfo Frequency Frekvence LFO + Seconds Sekund + Regen Obnov + Noise Šum + Invert Převrátit @@ -2241,57 +2779,70 @@ Ověřte si prosím, zda máte povolen zápis do souboru a do složky, ve které FlangerControlsDialog - Delay Time: - Délka zpoždění: - - - Feedback Amount: - Velikost zpětné vazby: - - - White Noise Amount: - Množství bílého šumu: - - + DELAY ZPOŽ + + Delay Time: + Délka zpoždění: + + + RATE POMĚR + + Period: + Perioda: + + + AMNT MNOŽ + Amount: Množství: + FDBK ZP. VAZ + + Feedback Amount: + Velikost zpětné vazby: + + + NOISE ŠUM - Invert - Převrátit + + White Noise Amount: + Množství bílého šumu: - Period: - Perioda: + + Invert + Převrátit FxLine + Channel send amount Množství odeslaného kanálu + The FX channel receives input from one or more instrument tracks. It in turn can be routed to multiple other FX channels. LMMS automatically takes care of preventing infinite loops for you and doesn't allow making a connection that would result in an infinite loop. @@ -2308,22 +2859,27 @@ Efektové kanály můžete odstranit nebo přesunout v kontextové nabídce, kte + Move &left Přesunout do&leva + Move &right Přesun dop&rava + Rename &channel Přejmenovat &kanál + R&emove channel Př&esunout kanál + Remove &unused channels Odstranit nepo&užívané kanály @@ -2331,22 +2887,29 @@ Efektové kanály můžete odstranit nebo přesunout v kontextové nabídce, kte FxMixer + Master Hlavní + + + FX %1 Efekt %1 + Volume Hlasitost + Mute Ztlumit + Solo Sólo @@ -2354,26 +2917,32 @@ Efektové kanály můžete odstranit nebo přesunout v kontextové nabídce, kte FxMixerView + FX-Mixer Efektový mixážní panel + FX Fader %1 Efektový fader %1 + Mute Ztlumit + Mute this FX channel Ztlumit tento efektový kanál + Solo Sólo + Solo FX channel Sólovat efektový kanál @@ -2381,6 +2950,8 @@ Efektové kanály můžete odstranit nebo přesunout v kontextové nabídce, kte FxRoute + + Amount to send from channel %1 to channel %2 Množství k odeslání z kanálu %1 do kanálu %2 @@ -2388,14 +2959,17 @@ Efektové kanály můžete odstranit nebo přesunout v kontextové nabídce, kte GigInstrument + Bank Banka + Patch Patch + Gain Zisk @@ -2403,46 +2977,58 @@ Efektové kanály můžete odstranit nebo přesunout v kontextové nabídce, kte GigInstrumentView + Open other GIG file Otevřít jiný GIG soubor + Click here to open another GIG file Klepněte sem pro otevření jiného GIG souboru + Choose the patch Vybrat patch + Click here to change which patch of the GIG file to use Klepněte sem pro změnu patche GIG souboru + + Change which instrument of the GIG file is being played Změnit přehrávaný nástroj GIG souboru + Which GIG file is currently being used Který GIG soubor je právě používán + Which patch of the GIG file is currently being used Který patch GIG souboru je právě používán + Gain - Zisk + Zesílení + Factor to multiply samples by Vynásobit vzorky x + Open GIG file Otevřít GIG soubor + GIG Files (*.gig) GIG soubory (*.gig) @@ -2450,42 +3036,52 @@ Efektové kanály můžete odstranit nebo přesunout v kontextové nabídce, kte GuiApplication + Working directory Pracovní adresář + The LMMS working directory %1 does not exist. Create it now? You can change the directory later via Edit -> Settings. Pracovní adresář LMMS %1 neexistuje. Chcete jej nyní vytvořit? Změnu adresáře mžete provést později v nabídce Úpravy -> Nastavení. + Preparing UI Připravuji UI + Preparing song editor Připravuji editor skladby + Preparing mixer Připravuji mixážní panel + Preparing controller rack - Připravuji panel kontrolérů + Připravuji panel ovladačů + Preparing project notes Připravuji poznámky k projektu + Preparing beat/bassline editor Připravuji editor bicích/basů + Preparing piano roll Připravuji Piano roll + Preparing automation editor Připravuji Editor automatizace @@ -2493,650 +3089,814 @@ Efektové kanály můžete odstranit nebo přesunout v kontextové nabídce, kte InstrumentFunctionArpeggio + Arpeggio Arpeggio + Arpeggio type Typ arpeggia + Arpeggio range Rozsah arpeggia - Arpeggio time - Trvání arpeggia - - - Arpeggio gate - Brána arpeggia - - - Arpeggio direction - Směr arpeggia - - - Arpeggio mode - Styl arpeggia - - - Up - Nahoru - - - Down - Dolů - - - Up and down - Nahoru a dolů - - - Random - Náhodné - - - Free - Volné - - - Sort - Tříděné - - - Sync - Synchronizované - - - Down and up - Dolů a nahoru + + Cycle steps + Počet kroků v cyklu + Skip rate Míra vynechávání + Miss rate Míra míjení - Cycle steps - Počet kroků v cyklu + + Arpeggio time + Trvání arpeggia + + + + Arpeggio gate + Brána arpeggia + + + + Arpeggio direction + Směr arpeggia + + + + Arpeggio mode + Styl arpeggia + + + + Up + Nahoru + + + + Down + Dolů + + + + Up and down + Nahoru a dolů + + + + Down and up + Dolů a nahoru + + + + Random + Náhodné + + + + Free + Volné + + + + Sort + Tříděné + + + + Sync + Synchronizované InstrumentFunctionArpeggioView + ARPEGGIO ARPEGGIO + An arpeggio is a method playing (especially plucked) instruments, which makes the music much livelier. The strings of such instruments (e.g. harps) are plucked like chords. The only difference is that this is done in a sequential order, so the notes are not played at the same time. Typical arpeggios are major or minor triads, but there are a lot of other possible chords, you can select. Arpeggio je způsob hry (zejména na drnkací nástroje), který činí hudbu mnohem živější. Struny těchto nástrojů (např. harfy) jsou rozezněny jako v akordech. Jediným rozdílem je, že se tak stane sekvenčně, takže tóny nejsou zahrány ve stejnou dobu. Typickým arpeggiem jsou durové a mollové trojzvuky, ale možných dalších akordů, které si můžete vybrat, je spousta. + RANGE ROZSAH + Arpeggio range: Rozsah arpeggia: + octave(s) oktáva(y) + Use this knob for setting the arpeggio range in octaves. The selected arpeggio will be played within specified number of octaves. Tento otočný ovladač použijte pro nastavení rozsahu arpeggia v oktávách. Vybrané arpeggio bude zahráno ve zvoleném počtu oktáv. - TIME - TRVÁNÍ - - - Arpeggio time: - Trvání arpeggia: - - - ms - ms - - - Use this knob for setting the arpeggio time in milliseconds. The arpeggio time specifies how long each arpeggio-tone should be played. - Tento otočný ovladač nastavuje trvání arpeggia v milisekundách. Trvání arpeggia udává, jak dlouho bude každý tón arpeggia přehráván. - - - GATE - BRÁNA - - - Arpeggio gate: - Brána arpeggia: - - - % - % - - - Use this knob for setting the arpeggio gate. The arpeggio gate specifies the percent of a whole arpeggio-tone that should be played. With this you can make cool staccato arpeggios. - Tento otočný ovladač nastavuje bránu arpeggia. Brána arpeggia určuje procento délky jednotlivých arpeggiových tónů, které budou zahrány. Pomocí brány arpeggia můžete udělat skvělé staccatové arpeggio. - - - Chord: - Akord: - - - Direction: - Směr: - - - Mode: - Styl: - - - SKIP - VYNECH - - - Skip rate: - Míra vynechávání: - - - The skip function will make the arpeggiator pause one step randomly. From its start in full counter clockwise position and no effect it will gradually progress to full amnesia at maximum setting. - Funkce vynechávání způsobí, že arpeggiator náhodně pozastaví některý krok. Od počáteční pozice, kde nemá žádný efekt, se po směru hodinových ručiček efekt stupňuje až po maximální nastavení, kdy vynechá vše. - - - MISS - MÍJ - - - Miss rate: - Míra míjení: - - - The miss function will make the arpeggiator miss the intended note. - Funkce míjení způsobí, že arpeggiator netrefí dotyčnou notu. - - + CYCLE CYKL + Cycle notes: Počet not v cyklu: + note(s) nota(y) + Jumps over n steps in the arpeggio and cycles around if we're over the note range. If the total note range is evenly divisible by the number of steps jumped over you will get stuck in a shorter arpeggio or even on one note. Skočí přes n kroků v arpeggiu a pokud přesáhne rozsah not, zacyklí se zde. Je-li je celkový rozsah not rovnoměrně dělitelný počtem kroků nad rozdah, uvíznete v kratším arpeggiu nebo dokonce na jedné notě. + + + SKIP + VYNECH + + + + Skip rate: + Míra vynechávání: + + + + + + % + % + + + + The skip function will make the arpeggiator pause one step randomly. From its start in full counter clockwise position and no effect it will gradually progress to full amnesia at maximum setting. + Funkce vynechávání způsobí, že arpeggiator náhodně pozastaví některý krok. Od počáteční pozice, kde nemá žádný efekt, se po směru hodinových ručiček efekt stupňuje až po maximální nastavení, kdy vynechá vše. + + + + MISS + MÍJ + + + + Miss rate: + Míra míjení: + + + + The miss function will make the arpeggiator miss the intended note. + Funkce míjení způsobí, že arpeggiator netrefí dotyčnou notu. + + + + TIME + TRVÁNÍ + + + + Arpeggio time: + Trvání arpeggia: + + + + ms + ms + + + + Use this knob for setting the arpeggio time in milliseconds. The arpeggio time specifies how long each arpeggio-tone should be played. + Tento otočný ovladač nastavuje trvání arpeggia v milisekundách. Trvání arpeggia udává, jak dlouho bude každý tón arpeggia přehráván. + + + + GATE + BRÁNA + + + + Arpeggio gate: + Brána arpeggia: + + + + Use this knob for setting the arpeggio gate. The arpeggio gate specifies the percent of a whole arpeggio-tone that should be played. With this you can make cool staccato arpeggios. + Tento otočný ovladač nastavuje bránu arpeggia. Brána arpeggia určuje procento délky jednotlivých arpeggiových tónů, které budou zahrány. Pomocí brány arpeggia můžete udělat skvělé staccatové arpeggio. + + + + Chord: + Akord: + + + + Direction: + Směr: + + + + Mode: + Styl: + InstrumentFunctionNoteStacking + octave Oktáva + + Major Dur + Majb5 Maj5b + minor Moll + minb5 m5b + sus2 sus2 + sus4 sus4 + aug aug + augsus4 aug sus4 + tri tri + 6 6 + 6sus4 6 sus4 + 6add9 6 add9 + m6 m6 + m6add9 m6 add9 + 7 7 + 7sus4 7 sus4 + 7#5 7/5# + 7b5 7/5b + 7#9 7/9# + 7b9 7/9b + 7#5#9 7/5#/9# + 7#5b9 7/5#/9b + 7b5b9 7/5b/9b + 7add11 7 add11 + 7add13 7 add13 + 7#11 7/11# + Maj7 Maj7 + Maj7b5 Maj7/5b + Maj7#5 Maj7/5# + Maj7#11 Maj7/11# + Maj7add13 Maj7 add13 + m7 m7 + m7b5 m7/5b + m7b9 m7/9b + m7add11 m7 add11 + m7add13 m7 add13 + m-Maj7 m-Maj7 + m-Maj7add11 m-Maj7 add11 + m-Maj7add13 m-Maj7 add13 + 9 9 + 9sus4 9 sus4 + add9 add9 + 9#5 9/5# + 9b5 9/5b + 9#11 9/11# + 9b13 9/13b + Maj9 Maj9 + Maj9sus4 Maj9 sus4 + Maj9#5 Maj9/5# + Maj9#11 Maj9/11# + m9 m9 + madd9 m add9 + m9b5 m9/5b + m9-Maj7 m9-Maj7 + 11 11 + 11b9 11/9b + Maj11 Maj11 + m11 m11 + m-Maj11 m-Maj11 + 13 13 + 13#9 13/9# + 13b9 13/9b + 13b5b9 13/9b/5b + Maj13 Maj13 + m13 m13 + m-Maj13 m-Maj13 + Harmonic minor Mollová harmonická + Melodic minor Mollová melodická + Whole tone Celotónová stupnice + Diminished Zmenšená + Major pentatonic Durová pentatonika + Minor pentatonic Mollová pentatonika + Jap in sen Japonská (in sen) stupnice + Major bebop Durová bebopová + Dominant bebop Dominantní bebopová + Blues Bluesová stupnice + Arabic Arabská + Enigmatic Enigmatická + Neopolitan Neapolská + Neopolitan minor Mollová neapolská + Hungarian minor Mollová maďarská + Dorian Dórská - Phrygolydian - Frygická + + Phrygian + Frygický + Lydian Lydická + Mixolydian Mixolydická + Aeolian Aiolská + Locrian Lokrická - Chords - Akordy - - - Chord type - Typ akordu - - - Chord range - Rozsah akordu - - + Minor Moll + Chromatic Chromatická + Half-Whole Diminished Zmenšená (půltón–celý tón) + 5 5 + Phrygian dominant Frygická dominanta + Persian Perská + + + Chords + Akordy + + + + Chord type + Typ akordu + + + + Chord range + Rozsah akordu + InstrumentFunctionNoteStackingView - RANGE - ROZSAH - - - Chord range: - Rozsah akordu: - - - octave(s) - oktáva(y) - - - Use this knob for setting the chord range in octaves. The selected chord will be played within specified number of octaves. - Tento otočný ovladač nastavuje rozsah akordů v oktávách. Vybraný akord bude zahrán ve zvoleném počtu oktáv. - - + STACKING VRSTVENÍ + Chord: Akord: + + + RANGE + ROZSAH + + + + Chord range: + Rozsah akordu: + + + + octave(s) + oktáva(y) + + + + Use this knob for setting the chord range in octaves. The selected chord will be played within specified number of octaves. + Tento otočný ovladač nastavuje rozsah akordů v oktávách. Vybraný akord bude zahrán ve zvoleném počtu oktáv. + InstrumentMidiIOView + ENABLE MIDI INPUT POVOLIT MIDI VSTUP + + CHANNEL KANÁL + + VELOCITY DYNAM + ENABLE MIDI OUTPUT POVOLIT MIDI VÝSTUP + PROGRAM PROGRAM - MIDI devices to receive MIDI events from - MIDI zařízení pro přijímání MIDI událostí - - - MIDI devices to send MIDI events to - MIDI zařízení pro odesílání MIDI událostí - - + NOTE NOTA + + MIDI devices to receive MIDI events from + MIDI zařízení pro přijímání MIDI událostí + + + + MIDI devices to send MIDI events to + MIDI zařízení pro odesílání MIDI událostí + + + CUSTOM BASE VELOCITY VLASTNÍ VÝCHOZÍ DYNAMIKA + Specify the velocity normalization base for MIDI-based instruments at 100% note velocity Udává výchozí úroveň dynamiky pro MIDI nástroje při 100 % dynamiky tónu + BASE VELOCITY VÝCHOZÍ DYNAMIKA @@ -3144,137 +3904,171 @@ Efektové kanály můžete odstranit nebo přesunout v kontextové nabídce, kte InstrumentMiscView + MASTER PITCH - HLAVNÍ LADĚNÍ + TRANSPOZICE + Enables the use of Master Pitch - Umožní použití hlavního ladění + Umožní použití transpozice InstrumentSoundShaping + VOLUME HLASITOST + Volume Hlasitost + CUTOFF SEŘÍZNUTÍ + + Cutoff frequency Frekvence oříznutí + RESO REZONANCE + Resonance Rezonance + Envelopes/LFOs Obálky/LFO + Filter type Typ filtru + Q/Resonance Q/rezonance + LowPass Dolní propust + HiPass Horní propust + BandPass csg Pásmová propust csg + BandPass czpg Pásmová propust czpg + Notch Pásmová zádrž + Allpass Všepásmový filtr + Moog Moogův filtr + 2x LowPass 2x dolní propust + RC LowPass 12dB RC dolní propust 12dB + RC BandPass 12dB RC pásmová propust 12dB + RC HighPass 12dB RC horní propust 12dB + RC LowPass 24dB RC dolní propust 24dB + RC BandPass 24dB RC pásmová propust 24dB + RC HighPass 24dB RC horní propust 24dB + Vocal Formant Filter Vokální formantový filtr + 2x Moog 2x Moogův filtr + SV LowPass SV dolní propust + SV BandPass SV pásmová propust + SV HighPass SV horní propust + SV Notch SV pásmová zádrž + Fast Formant Rychlý formantový filtr + Tripole Třípólový filtr @@ -3282,50 +4076,62 @@ Efektové kanály můžete odstranit nebo přesunout v kontextové nabídce, kte InstrumentSoundShapingView + TARGET CÍL: + These tabs contain envelopes. They're very important for modifying a sound, in that they are almost always necessary for substractive synthesis. For example if you have a volume envelope, you can set when the sound should have a specific volume. If you want to create some soft strings then your sound has to fade in and out very softly. This can be done by setting large attack and release times. It's the same for other envelope targets like panning, cutoff frequency for the used filter and so on. Just monkey around with it! You can really make cool sounds out of a saw-wave with just some envelopes...! Tato stránka obsahuje obálky. Ty jsou velmi důležité pro úpravu zvuku a obvykle také i nezbytné pro rozdílovou (subtraktivní) syntézu. Pokud máte například obálku hlasitosti, můžete nastavit, kdy má mít zvuk jakou sílu. Pokud chcete vytvořit něco jako smyčce, váš zvuk by měl mít velmi měkké nasazení i ukončení tónu. Toho dosáhneme nastavením dlouhého času náběhu i uvolnění. Totéž se týká ostatních druhů obálek, jako je obálka panorámatu, frekvence odříznutí pro použití u filtrů apod. Prostě si s tím můžete vyhrát dle libosti! Můžete vytvořit opravdu úžasné zvuky třeba jen z pilovité vlny pomocí vhodných obálek...! + FILTER FILTR + Here you can select the built-in filter you want to use for this instrument-track. Filters are very important for changing the characteristics of a sound. Zde si můžete vybrat z vestavěných filtrů, které chcete použít pro tuto stopu nástroje. Filtry jsou velmi důležité pro změnu charakteristiky zvuku. - Hz - Hz - - - Use this knob for setting the cutoff frequency for the selected filter. The cutoff frequency specifies the frequency for cutting the signal by a filter. For example a lowpass-filter cuts all frequencies above the cutoff frequency. A highpass-filter cuts all frequencies below cutoff frequency, and so on... - Tento otočný ovladač nastavuje frekvenci odříznutí pro vybraný filtr. Frekvence odříznutí určuje frekvenci pro odříznutí signálu filtrem. Například filtr typu dolní propust (low-pass) odstřihne všechny frekvence, které jsou vyšší než frekvence odříznutí. Filtr typu horní propust (high-pass) odstřihne všechny frekvence, které jsou nižší než frekvence odříznutí atd... - - - RESO - REZO - - - Resonance: - Rezonance: - - - Use this knob for setting Q/Resonance for the selected filter. Q/Resonance tells the filter how much it should amplify frequencies near Cutoff-frequency. - Tento otočný ovladač nastavuje Q/rezonanci pro vybraný filtr. Q/rezonance určuje, jak hodně filtr zesílí frekvence poblíž frekvence oříznutí. - - + FREQ FREKV + cutoff frequency: Frekvence oříznutí: + + Hz + Hz + + + + Use this knob for setting the cutoff frequency for the selected filter. The cutoff frequency specifies the frequency for cutting the signal by a filter. For example a lowpass-filter cuts all frequencies above the cutoff frequency. A highpass-filter cuts all frequencies below cutoff frequency, and so on... + Tento otočný ovladač nastavuje frekvenci odříznutí pro vybraný filtr. Frekvence odříznutí určuje frekvenci pro odříznutí signálu filtrem. Například filtr typu dolní propust (low-pass) odstřihne všechny frekvence, které jsou vyšší než frekvence odříznutí. Filtr typu horní propust (high-pass) odstřihne všechny frekvence, které jsou nižší než frekvence odříznutí atd... + + + + RESO + REZO + + + + Resonance: + Rezonance: + + + + Use this knob for setting Q/Resonance for the selected filter. Q/Resonance tells the filter how much it should amplify frequencies near Cutoff-frequency. + Tento otočný ovladač nastavuje Q/rezonanci pro vybraný filtr. Q/rezonance určuje, jak hodně filtr zesílí frekvence poblíž frekvence oříznutí. + + + Envelopes, LFOs and filters are not supported by the current instrument. Obálky, LFO a filtry nejsou podporovány stávajícím nástrojem. @@ -3333,85 +4139,107 @@ Efektové kanály můžete odstranit nebo přesunout v kontextové nabídce, kte InstrumentTrack - unnamed_track - nepojmenovaná_stopa - - - Volume - Hlasitost - - - Panning - Panoráma - - - Pitch - Ladění - - - FX channel - Efektový kanál - - - Default preset - Výchozí předvolba - - + With this knob you can set the volume of the opened channel. Tímto otočným ovladačem můžete nastavit hlasitost otevřeného kanálu. + + + unnamed_track + nepojmenovaná_stopa + + + Base note Základní nota + + Volume + Hlasitost + + + + Panning + Panoráma + + + + Pitch + Ladění + + + Pitch range Výškový rozsah + + FX channel + Efektový kanál + + + Master Pitch - Hlavní ladění + Transpozice + + + + + Default preset + Výchozí předvolba InstrumentTrackView + Volume Hlasitost + Volume: Hlasitost: + VOL HLA + Panning Panoráma + Panning: Panoráma: + PAN PAN + MIDI MIDI + Input Vstup + Output Výstup + FX %1: %2 Efekt %1: %2 @@ -3419,110 +4247,137 @@ Efektové kanály můžete odstranit nebo přesunout v kontextové nabídce, kte InstrumentTrackWindow + GENERAL SETTINGS HLAVNÍ NASTAVENÍ - Instrument volume - Hlasitost nástroje - - - Volume: - Hlasitost: - - - VOL - HLA - - - Panning - Panoráma - - - Panning: - Panoráma: - - - PAN - PAN - - - Pitch - Ladění - - - Pitch: - Ladění: - - - cents - centů - - - PITCH - LADĚNÍ - - - FX channel - Efektový kanál - - - FX - EFEKT - - - Save preset - Uložit předvolbu - - - XML preset file (*.xpf) - XML soubor předvoleb (*.xpf) - - - Pitch range (semitones) - Rozsah výšky (v půltónech) - - - RANGE - ROZSAH - - - Save current instrument track settings in a preset file - Uložit aktuální nastavení nástrojové stopy do souboru předvoleb - - - Click here, if you want to save current instrument track settings in a preset file. Later you can load this preset by double-clicking it in the preset-browser. - Klepněte sem, chcete-li uložit aktuální nastavení nástrojové stopy do souboru předvoleb. Později můžete nahrát tuto předvolbu poklepáním na prohlížeč předvoleb. - - + Use these controls to view and edit the next/previous track in the song editor. Použije tyto ovládací prvky pro zobrazení a editaci další/předchozí stopy v editoru skladby. + + Instrument volume + Hlasitost nástroje + + + + Volume: + Hlasitost: + + + + VOL + HLA + + + + Panning + Panoráma + + + + Panning: + Panoráma: + + + + PAN + PAN + + + + Pitch + Ladění + + + + Pitch: + Ladění: + + + + cents + centů + + + + PITCH + LADĚNÍ + + + + Pitch range (semitones) + Rozsah výšky (v půltónech) + + + + RANGE + ROZSAH + + + + FX channel + Efektový kanál + + + + FX + EFEKT + + + + Save current instrument track settings in a preset file + Uložit aktuální nastavení nástrojové stopy do souboru předvoleb + + + + Click here, if you want to save current instrument track settings in a preset file. Later you can load this preset by double-clicking it in the preset-browser. + Klepněte sem, chcete-li uložit aktuální nastavení nástrojové stopy do souboru předvoleb. Později můžete nahrát tuto předvolbu poklepáním na prohlížeč předvoleb. + + + SAVE ULOŽIT + Envelope, filter & LFO Obálka, filtr a LFO + Chord stacking & arpeggio Vrstvení akordů a arpeggio + Effects Efekty + MIDI settings MIDI nastavení + Miscellaneous Různé + + Save preset + Uložit předvolbu + + + + XML preset file (*.xpf) + XML soubor předvoleb (*.xpf) + + + Plugin Plugin @@ -3530,25 +4385,30 @@ Efektové kanály můžete odstranit nebo přesunout v kontextové nabídce, kte Knob + Set linear Lineární zobrazení + Set logarithmic Logaritmické zobrazení - Please enter a new value between %1 and %2: - Vložte prosím novou hodnotu mezi %1 a %2: - - + Please enter a new value between -96.0 dBFS and 6.0 dBFS: Zadejte prosím novou hodnotu mezi -96.0 dBFS a 6.0 dBFS: + + + Please enter a new value between %1 and %2: + Vložte prosím novou hodnotu mezi %1 a %2: + LadspaControl + Link channels Propojit kanály @@ -3556,10 +4416,12 @@ Efektové kanály můžete odstranit nebo přesunout v kontextové nabídce, kte LadspaControlDialog + Link Channels Propojit kanály + Channel Kanál @@ -3567,14 +4429,17 @@ Efektové kanály můžete odstranit nebo přesunout v kontextové nabídce, kte LadspaControlView + Link channels Propojit kanály + Value: Hodnota: + Sorry, no help available. Promiňte, nápověda není k dispozici. @@ -3582,6 +4447,7 @@ Efektové kanály můžete odstranit nebo přesunout v kontextové nabídce, kte LadspaEffect + Unknown LADSPA plugin %1 requested. Je požadován neznámý LADSPA plugin %1. @@ -3589,6 +4455,7 @@ Efektové kanály můžete odstranit nebo přesunout v kontextové nabídce, kte LcdSpinBox + Please enter a new value between %1 and %2: Vložte prosím novou hodnotu mezi %1 a %2: @@ -3596,18 +4463,26 @@ Efektové kanály můžete odstranit nebo přesunout v kontextové nabídce, kte LeftRightNav + + + Previous Předchozí + + + Next Další + Previous (%1) Předchozí (%1) + Next (%1) Další (%1) @@ -3615,30 +4490,37 @@ Efektové kanály můžete odstranit nebo přesunout v kontextové nabídce, kte LfoController + LFO Controller Ovladač LFO + Base value Základní hodnota + Oscillator speed Rychlost oscilátoru + Oscillator amount Míra oscilátoru + Oscillator phase Fáze oscilátoru + Oscillator waveform Vlna oscilátoru + Frequency Multiplier Frekvenční multiplikátor @@ -3646,115 +4528,142 @@ Efektové kanály můžete odstranit nebo přesunout v kontextové nabídce, kte LfoControllerDialog + LFO LFO + LFO Controller Ovladač LFO + BASE ZÁKL + Base amount: Základní míra: + todo udělat + SPD RYCH + LFO-speed: Rychlost LFO: + Use this knob for setting speed of the LFO. The bigger this value the faster the LFO oscillates and the faster the effect. Tento otočný ovladač nastavuje rychlost LFO. Zvýšením hodnoty se zrychlí kmitání LFO a průběh efektu. + + AMNT + MNOŽ + + + Modulation amount: Hloubka modulace: + Use this knob for setting modulation amount of the LFO. The bigger this value, the more the connected control (e.g. volume or cutoff-frequency) will be influenced by the LFO. Tento otočný ovladač nastavuje množství modulace LFO. Čím vyšší bude tato hodnota, tím více budou propojené parametry (např. hlasitost nebo frekvence odříznutí) ovlivněny LFO. + PHS FÁZ + Phase offset: Posun fáze: + degrees stupňů + With this knob you can set the phase offset of the LFO. That means you can move the point within an oscillation where the oscillator begins to oscillate. For example if you have a sine-wave and have a phase-offset of 180 degrees the wave will first go down. It's the same with a square-wave. Tímto otočným ovladačem můžete nastavit fázový posun LFO. To znamená, že můžete posunout bod, ve kterém oscilátor začne kmitat. Například pokud máte sinusovou vlnu s fázovým posunem 180 stupňů, vlna půjde nejdříve dolů. Totéž se stane u vlny pravoúhlé. + Click here for a sine-wave. Klepněte sem pro sinusovou vlnu. + Click here for a triangle-wave. Klepněte sem pro trojúhelníkovou vlnu. + Click here for a saw-wave. Klepněte sem pro pilovitou vlnu. + Click here for a square-wave. Klepněte sem pro pravoúhlou vlnu. + + Click here for a moog saw-wave. + Klepněte sem pro pilovitou vlnu typu Moog. + + + Click here for an exponential wave. Klepněte sem pro exponenciální vlnu. + Click here for white-noise. Klepněte sem pro bílý šum. + Click here for a user-defined shape. Double click to pick a file. Klepněte sem pro uživatelem definovaný tvar. Poklepejte pro výběr souboru. - - Click here for a moog saw-wave. - Klepněte sem pro pilovitou vlnu typu Moog. - - - AMNT - MNOŽ - LmmsCore + Generating wavetables Generuji vlny + Initializing data structures Inicializuji datové struktury + Opening audio and midi devices Spouštím zvuková a MIDI zařízení + Launching mixer threads Spouštím vlákna mixážního panelu @@ -3762,397 +4671,500 @@ Poklepejte pro výběr souboru. MainWindow - &New - &Nový - - - &Open... - &Otevřít... - - - &Save - &Uložit - - - Save &As... - Uložit &jako... - - - Import... - Importovat... - - - E&xport... - E&xportovat... - - - &Quit - &Ukončit - - - &Edit - Úpr&avy - - - Settings - Nastavení - - - &Tools - &Nástroje - - - &Help - &Nápověda - - - Help - Nápověda - - - What's this? - Co je to? - - - About - O LMMS - - - Create new project - Vytvořit nový projekt - - - Create new project from template - Vytvořit nový projekt ze šablony - - - Open existing project - Otevřít existující projekt - - - Recently opened projects - Naposledy otevřené projekty - - - Save current project - Uložit aktuální projekt - - - Export current project - Exportovat aktuální projekt - - - Song Editor - Editor skladby - - - By pressing this button, you can show or hide the Song-Editor. With the help of the Song-Editor you can edit song-playlist and specify when which track should be played. You can also insert and move samples (e.g. rap samples) directly into the playlist. - Stisknutím tohoto tlačítka zobrazíte nebo skryjete Editor skladby. S jeho pomocí můžete upravovat playlist skladby a určit, kdy a která stopa má být přehrána. Můžete také vložit a přesunovat vzorky (např. rapové) přímo do playlistu. - - - Beat+Bassline Editor - Editor bicích/basů - - - By pressing this button, you can show or hide the Beat+Bassline Editor. The Beat+Bassline Editor is needed for creating beats, and for opening, adding, and removing channels, and for cutting, copying and pasting beat and bassline-patterns, and for other things like that. - Stisknutím tohoto tlačítka zobrazíte nebo skryjete editor bicích/basů. Tento editor je nezbytný pro tvorbu beatů, otevírání, přidávání či odebírání kanálů a dále pro vyjímání, kopírování a vkládání beatů, bicích/basových patternů apod. - - - Piano Roll - Piano roll - - - Click here to show or hide the Piano-Roll. With the help of the Piano-Roll you can edit melodies in an easy way. - Klepněte sem, pokud chcete ukázat nebo skrýt Piano roll. S pomocí Piano rollu můžete jednoduchým způsobem upravovat melodie. - - - Automation Editor - Editor automatizace - - - Click here to show or hide the Automation Editor. With the help of the Automation Editor you can edit dynamic values in an easy way. - Klepněte sem, pokud chcete ukázat nebo skrýt Editor automatizace. S pomocí Editoru automatizace můžete jednoduchým způsobem upravovat proměnlivý průběh hodnot. - - - FX Mixer - Efektový mixážní panel - - - Click here to show or hide the FX Mixer. The FX Mixer is a very powerful tool for managing effects for your song. You can insert effects into different effect-channels. - Klepněte sem, pokud chcete ukázat nebo skrýt efektový (FX) mixážní panel. Efektový mixážní panel je velmi výkonný nástroj pro správu efektů ve vaší skladbě. Efekty můžete vkládat do různých efektových kanálů. - - - Project Notes - Poznámky k projektu - - - Click here to show or hide the project notes window. In this window you can put down your project notes. - Klepněte sem, pokud chcete ukázat nebo schovat okno pro poznámky. V tomto okně lze vkládat vaše poznámky k projektu. - - - Controller Rack - Panel kontrolérů - - - Untitled - Nepojmenovaný - - - LMMS %1 - LMMS %1 - - - Project not saved - Projekt není uložen - - - The current project was modified since last saving. Do you want to save it now? - Aktuální projekt byl od posledního uložení změněn. Chcete jej nyní uložit? - - - Help not available - Nápověda není dostupná - - - Currently there's no help available in LMMS. -Please visit http://lmms.sf.net/wiki for documentation on LMMS. - V současnosti není v LMMS nápověda dostupná. -Navštivte prosím stránku s dokumentací k LMMS na adrese http://lmms.sf.net/wiki. - - - LMMS (*.mmp *.mmpz) - LMMS (*.mmp *.mmpz) - - - Version %1 - Verze %1 - - + Configuration file Soubor nastavení + Error while parsing configuration file at line %1:%2: %3 Chyba při kontrole konfiguračního souboru na řádku %1:%2: %3 - Volumes - Hlasitosti - - - Undo - Zpět - - - Redo - Znovu - - - My Projects - Moje projekty - - - My Samples - Moje samply - - - My Presets - Moje předvolby - - - My Home - Domů - - - My Computer - Můj počítač - - - &File - &Soubor - - - &Recently Opened Projects - &Naposledy otevřené projekty - - - Save as New &Version - Uložit jako novou &verzi - - - E&xport Tracks... - E&xportovat stopy... - - - Online Help - Nápověda online - - - What's This? - Co je to? - - - Open Project - Otevřít projekt - - - Save Project - Uložit projekt - - - Project recovery - Obnovení projektu - - - There is a recovery file present. It looks like the last session did not end properly or another instance of LMMS is already running. Do you want to recover the project of this session? - Je k dispozici soubor pro obnovu. Zdá se, že poslední práce nebyla správně ukončena nebo že je již spuštěna jiná instance LMMS. Chcete obnovit tuto verzi projektu? - - - Recover - Obnovit - - - Recover the file. Please don't run multiple instances of LMMS when you do this. - Obnovit soubor. Před dokončením prosím nespouštějte další instance LMMS. - - - Discard - Zrušit - - - Launch a default session and delete the restored files. This is not reversible. - Spustit LMMS do výchozího stavu a smazat obnovené soubory. Tento krok je nevratný. - - - Preparing plugin browser - Připravuji prohlížeč pluginů - - - Preparing file browsers - Připravuji prohlížeč souborů - - - Root directory - Kořenový adresář - - - Loading background artwork - Načítám grafiku prostředí - - - New from template - Nový z šablony - - - Save as default template - Uložit jako výchozí šablonu - - - &View - &Zobrazení - - - Toggle metronome - Zapnout/Vypnout metronom - - - Show/hide Song-Editor - Zobrazit/Skrýt editor skladby - - - Show/hide Beat+Bassline Editor - Zobrazit/Skrýt editor bicích/basů - - - Show/hide Piano-Roll - Zobrazit/Skrýt Piano roll - - - Show/hide Automation Editor - Zobrazit/Skrýt Editor automatizace - - - Show/hide FX Mixer - Zobrazit/Skrýt efektový mixážní panel - - - Show/hide project notes - Zobrazit/Skrýt poznámky k projektu - - - Show/hide controller rack - Zobrazit/Skrýt panel ovladačů - - - Recover session. Please save your work! - Obnovit projekt. Uložte prosím svou práci! - - - Recovered project not saved - Obnovený projekt není uložen - - - This project was recovered from the previous session. It is currently unsaved and will be lost if you don't save it. Do you want to save it now? - Tento projekt byl obnoven z minulého spuštění LMMS. Zatím není uložen a pokud tak neučiníte, práce bude ztracena. Chcete jej nyní uložit? - - - LMMS Project - Projekt LMMS - - - LMMS Project Template - Šablona projektu LMMS - - - Overwrite default template? - Přepsat výchozí šablonu? - - - This will overwrite your current default template. - Tímto se přepíše vaše nynější výchozí šablona. - - - Smooth scroll - Plynulé posouvání - - - Enable note labels in piano roll - Povolit názvy tónů v Piano rollu - - - Save project template - Uložit šablonu projektu - - - Volume as dBFS - Hlasitost v dBFS - - + Could not open file Nemohu otevřít soubor + Could not open file %1 for writing. Please make sure you have write permission to the file and the directory containing the file and try again! Nelze otevřít soubor %1 pro zápis. Ujistěte se prosím, zda máte povolen zápis do souboru a do složky obsahující soubor a zkuste znovu! + + Project recovery + Obnovení projektu + + + + There is a recovery file present. It looks like the last session did not end properly or another instance of LMMS is already running. Do you want to recover the project of this session? + Je k dispozici soubor pro obnovu. Zdá se, že poslední práce nebyla správně ukončena nebo že je již spuštěna jiná instance LMMS. Chcete obnovit tuto verzi projektu? + + + + + + Recover + Obnovit + + + + Recover the file. Please don't run multiple instances of LMMS when you do this. + Obnovit soubor. Před dokončením prosím nespouštějte další instance LMMS. + + + + + + Discard + Zrušit + + + + Launch a default session and delete the restored files. This is not reversible. + Spustit LMMS do výchozího stavu a smazat obnovené soubory. Tento krok je nevratný. + + + + Version %1 + Verze %1 + + + + Preparing plugin browser + Připravuji prohlížeč pluginů + + + + Preparing file browsers + Připravuji prohlížeč souborů + + + + My Projects + Moje projekty + + + + My Samples + Moje samply + + + + My Presets + Moje předvolby + + + + My Home + Domů + + + + Root directory + Kořenový adresář + + + + Volumes + Hlasitosti + + + + My Computer + Můj počítač + + + + Loading background artwork + Načítám grafiku prostředí + + + + &File + &Soubor + + + + &New + &Nový + + + + New from template + Nový z šablony + + + + &Open... + &Otevřít... + + + + &Recently Opened Projects + &Naposledy otevřené projekty + + + + &Save + &Uložit + + + + Save &As... + Uložit &jako... + + + + Save as New &Version + Uložit jako novou &verzi + + + + Save as default template + Uložit jako výchozí šablonu + + + + Import... + Importovat... + + + + E&xport... + E&xportovat... + + + + E&xport Tracks... + E&xportovat stopy... + + + Export &MIDI... &Exportovat MIDI... + + + &Quit + &Ukončit + + + + &Edit + Úpr&avy + + + + Undo + Zpět + + + + Redo + Znovu + + + + Settings + Nastavení + + + + &View + &Zobrazení + + + + &Tools + &Nástroje + + + + &Help + &Nápověda + + + + Online Help + Nápověda online + + + + Help + Nápověda + + + + What's This? + Co je to? + + + + About + O LMMS + + + + Create new project + Vytvořit nový projekt + + + + Create new project from template + Vytvořit nový projekt ze šablony + + + + Open existing project + Otevřít existující projekt + + + + Recently opened projects + Naposledy otevřené projekty + + + + Save current project + Uložit aktuální projekt + + + + Export current project + Exportovat aktuální projekt + + + + What's this? + Co je to? + + + + Toggle metronome + Zapnout/Vypnout metronom + + + + Show/hide Song-Editor + Zobrazit/Skrýt editor skladby + + + + By pressing this button, you can show or hide the Song-Editor. With the help of the Song-Editor you can edit song-playlist and specify when which track should be played. You can also insert and move samples (e.g. rap samples) directly into the playlist. + Stisknutím tohoto tlačítka zobrazíte nebo skryjete Editor skladby. S jeho pomocí můžete upravovat playlist skladby a určit, kdy a která stopa má být přehrána. Můžete také vkládat a přesunovat samply (např. rapové) přímo do playlistu. + + + + Show/hide Beat+Bassline Editor + Zobrazit/Skrýt editor bicích/basů + + + + By pressing this button, you can show or hide the Beat+Bassline Editor. The Beat+Bassline Editor is needed for creating beats, and for opening, adding, and removing channels, and for cutting, copying and pasting beat and bassline-patterns, and for other things like that. + Stisknutím tohoto tlačítka zobrazíte nebo skryjete editor bicích/basů. Tento editor je nezbytný pro tvorbu beatů, otevírání, přidávání či odebírání kanálů a dále pro vyjímání, kopírování a vkládání beatů, bicích/basových záznamů apod. + + + + Show/hide Piano-Roll + Zobrazit/Skrýt Piano roll + + + + Click here to show or hide the Piano-Roll. With the help of the Piano-Roll you can edit melodies in an easy way. + Klepněte sem, pokud chcete ukázat nebo skrýt Piano roll. S pomocí Piano rollu můžete jednoduchým způsobem upravovat melodie. + + + + Show/hide Automation Editor + Zobrazit/Skrýt Editor automatizace + + + + Click here to show or hide the Automation Editor. With the help of the Automation Editor you can edit dynamic values in an easy way. + Klepněte sem, pokud chcete ukázat nebo skrýt Editor automatizace. S pomocí Editoru automatizace můžete jednoduchým způsobem upravovat proměnlivý průběh hodnot. + + + + Show/hide FX Mixer + Zobrazit/Skrýt efektový mixážní panel + + + + Click here to show or hide the FX Mixer. The FX Mixer is a very powerful tool for managing effects for your song. You can insert effects into different effect-channels. + Klepněte sem, pokud chcete ukázat nebo skrýt efektový (FX) mixážní panel. Efektový mixážní panel je velmi výkonný nástroj pro správu efektů ve vaší skladbě. Efekty můžete vkládat do různých efektových kanálů. + + + + Show/hide project notes + Zobrazit/Skrýt poznámky k projektu + + + + Click here to show or hide the project notes window. In this window you can put down your project notes. + Klepněte sem, pokud chcete ukázat nebo schovat okno pro poznámky. V tomto okně lze vkládat vaše poznámky k projektu. + + + + Show/hide controller rack + Zobrazit/Skrýt panel ovladačů + + + + Untitled + Nepojmenovaný + + + + Recover session. Please save your work! + Obnovit projekt. Uložte prosím svou práci! + + + + LMMS %1 + LMMS %1 + + + + Recovered project not saved + Obnovený projekt není uložen + + + + This project was recovered from the previous session. It is currently unsaved and will be lost if you don't save it. Do you want to save it now? + Tento projekt byl obnoven z minulého spuštění LMMS. Zatím není uložen a pokud tak neučiníte, práce bude ztracena. Chcete jej nyní uložit? + + + + Project not saved + Projekt není uložen + + + + The current project was modified since last saving. Do you want to save it now? + Aktuální projekt byl od posledního uložení změněn. Chcete jej nyní uložit? + + + + Open Project + Otevřít projekt + + + + LMMS (*.mmp *.mmpz) + LMMS (*.mmp *.mmpz) + + + + Save Project + Uložit projekt + + + + LMMS Project + Projekt LMMS + + + + LMMS Project Template + Šablona projektu LMMS + + + + Save project template + Uložit šablonu projektu + + + + Overwrite default template? + Přepsat výchozí šablonu? + + + + This will overwrite your current default template. + Tímto se přepíše vaše nynější výchozí šablona. + + + + Help not available + Nápověda není dostupná + + + + Currently there's no help available in LMMS. +Please visit http://lmms.sf.net/wiki for documentation on LMMS. + V současnosti není v LMMS nápověda dostupná. +Navštivte prosím stránku s dokumentací k LMMS na adrese http://lmms.sf.net/wiki. + + + + Song Editor + Editor skladby + + + + Beat+Bassline Editor + Editor bicích/basů + + + + Piano Roll + Piano roll + + + + Automation Editor + Editor automatizace + + + + FX Mixer + Efektový mixážní panel + + + + Project Notes + Poznámky k projektu + + + + Controller Rack + Panel ovladačů + + + + Volume as dBFS + Hlasitost v dBFS + + + + Smooth scroll + Plynulé posouvání + + + + Enable note labels in piano roll + Povolit názvy tónů v Piano rollu + MeterDialog + + Meter Numerator Počet dob v taktu + + Meter Denominator Délka doby v taktu + TIME SIG METRUM @@ -4160,10 +5172,12 @@ Ujistěte se prosím, zda máte povolen zápis do souboru a do složky obsahují MeterModel + Numerator Počet dob + Denominator Délka doby @@ -4171,29 +5185,36 @@ Ujistěte se prosím, zda máte povolen zápis do souboru a do složky obsahují MidiController + MIDI Controller - MIDI kontrolér + MIDI ovladač + unnamed_midi_controller - nepojmenovaný_midi_kontrolér + nepojmenovaný_midi_ovladač MidiImport + + Setup incomplete Nastavení není dokončeno + You do not have set up a default soundfont in the settings dialog (Edit->Settings). Therefore no sound will be played back after importing this MIDI file. You should download a General MIDI soundfont, specify it in settings dialog and try again. Nemáte nastaven výchozí soundfont v dialogovém okně (Edit-> Nastavení). Z tohoto důvodu nebude po importu MIDI souboru přehráván žádný zvuk. Stáhněte si nějaký General MIDI soundfont, zadejte jej v dialogovém okně nastavení a zkuste to znovu. + You did not compile LMMS with support for SoundFont2 player, which is used to add default sound to imported MIDI files. Therefore no sound will be played back after importing this MIDI file. Nelze zkompilovat LMMS s podporou přehrávače SoundFont2, který je použitý k přidání výchozího zvuku do importovaných MIDI souborů. Proto nebude po importování tohoto MIDI souboru přehráván žádný zvuk. + Track Stopa @@ -4201,11 +5222,13 @@ Ujistěte se prosím, zda máte povolen zápis do souboru a do složky obsahují MidiJack + JACK server down When JACK(JACK Audio Connection Kit) disconnects, it will show the following message (title) JACK server zhavaroval + The JACK server seems to be shuted down. When JACK(JACK Audio Connection Kit) disconnects, it will show the following message (dialog message) Zdá se, že JACK server zhavaroval. @@ -4214,53 +5237,65 @@ Ujistěte se prosím, zda máte povolen zápis do souboru a do složky obsahují MidiPort + Input channel Vstupní kanál + Output channel Výstupní kanál + Input controller - Vstupní kontrolér + Vstupní ovladač + Output controller - Výstupní kontrolér + Výstupní ovladač + Fixed input velocity Pevná vstupní dynamika + Fixed output velocity Pevná výstupní dynamika - Output MIDI program - Výstupní MIDI program - - - Receive MIDI-events - Přijímat MIDI události - - - Send MIDI-events - Posílat MIDI události - - + Fixed output note Pevná výstupní nota + + Output MIDI program + Výstupní MIDI program + + + Base velocity Výchozí dynamika + + + Receive MIDI-events + Přijímat MIDI události + + + + Send MIDI-events + Posílat MIDI události + MidiSetupWidget + DEVICE ZAŘÍZENÍ @@ -4268,474 +5303,595 @@ Ujistěte se prosím, zda máte povolen zápis do souboru a do složky obsahují MonstroInstrument + Osc 1 Volume Osc 1 hlasitost + Osc 1 Panning Osc 1 panoráma + Osc 1 Coarse detune Osc 1 hrubé rozladění + Osc 1 Fine detune left Osc 1 jemné rozladění vlevo + Osc 1 Fine detune right Osc 1 jemné rozladění vpravo + Osc 1 Stereo phase offset Osc 1 posun stereo fáze + Osc 1 Pulse width Osc 1 délka pulzu + Osc 1 Sync send on rise Osc 1 synchronizace při nárůstu + Osc 1 Sync send on fall Osc 1 synchronizace při poklesu + Osc 2 Volume Osc 2 hlasitost + Osc 2 Panning Osc 2 panoráma + Osc 2 Coarse detune Osc 2 hrubé rozladění + Osc 2 Fine detune left Osc 2 jemné rozladění vlevo + Osc 2 Fine detune right Osc 2 jemné rozladění vpravo + Osc 2 Stereo phase offset Osc 2 posun stereo fáze + Osc 2 Waveform Osc 2 vlna + Osc 2 Sync Hard Osc 2 pevná synchronizace + Osc 2 Sync Reverse Osc 2 reverzní synchronizace + Osc 3 Volume Osc 3 hlasitost + Osc 3 Panning Osc 3 panoráma + Osc 3 Coarse detune Osc 3 hrubé rozladění + Osc 3 Stereo phase offset Osc 3 posun stereo fáze + Osc 3 Sub-oscillator mix Osc 3 smíchání se sub-oscilátorem + Osc 3 Waveform 1 Osc 3 vlna 1 + Osc 3 Waveform 2 Osc 3 vlna 2 + Osc 3 Sync Hard Osc 3 pevná synchronizace + Osc 3 Sync Reverse Osc 3 reverzní synchronizace + LFO 1 Waveform LFO 1 vlna + LFO 1 Attack LFO 1 náběh + LFO 1 Rate LFO 1 rychlost + LFO 1 Phase LFO 1 fáze + LFO 2 Waveform LFO 2 vlna + LFO 2 Attack LFO 2 náběh + LFO 2 Rate LFO 2 rychlost + LFO 2 Phase LFO 2 fáze + Env 1 Pre-delay Obálka 1 předzpoždění + Env 1 Attack Obálka 1 náběh + Env 1 Hold Obálka 1 držení + Env 1 Decay Obálka 1 útlum + Env 1 Sustain Obálka 1 vydržení + Env 1 Release Obálka 1 uvolnění + Env 1 Slope Obálka 1 sklon + Env 2 Pre-delay Obálka 2 předzpoždění + Env 2 Attack Obálka 2 náběh + Env 2 Hold Obálka 2 držení + Env 2 Decay Obálka 2 útlum + Env 2 Sustain Obálka 2 vydržení + Env 2 Release Obálka 2 uvolnění + Env 2 Slope Obálka 2 sklon + Osc2-3 modulation Osc 2–3 modulace + Selected view Zvolený pohled + Vol1-Env1 Hla1-Obá1 + Vol1-Env2 Hla1-Obá2 + Vol1-LFO1 Hla1-LFO1 + Vol1-LFO2 Hla1-LFO2 + Vol2-Env1 Hla2-Obá1 + Vol2-Env2 Hla2-Obá2 + Vol2-LFO1 Hla2-LFO1 + Vol2-LFO2 Hla2-LFO2 + Vol3-Env1 Hla3-Obá1 + Vol3-Env2 Hla3-Obá2 + Vol3-LFO1 Hla3-LFO1 + Vol3-LFO2 Hla3-LFO2 + Phs1-Env1 Fáz1-Obá1 + Phs1-Env2 Fáz1-Obá2 + Phs1-LFO1 Fáz1-LFO1 + Phs1-LFO2 Fáz1-LFO2 + Phs2-Env1 Fáz2-Obá1 + Phs2-Env2 Fáz2-Obá2 + Phs2-LFO1 Fáz2-LFO1 + Phs2-LFO2 Fáz2-LFO2 + Phs3-Env1 Fáz3-Obá1 + Phs3-Env2 Fáz3-Obá2 + Phs3-LFO1 Fáz3-LFO1 + Phs3-LFO2 Fáz3-LFO2 + Pit1-Env1 Výš1-Obá1 + Pit1-Env2 Výš1-Obá2 + Pit1-LFO1 Výš1-LFO1 + Pit1-LFO2 Výš1-LFO2 + Pit2-Env1 Výš2-Obá1 + Pit2-Env2 Výš2-Obá2 + Pit2-LFO1 Výš2-LFO1 + Pit2-LFO2 Výš2-LFO2 + Pit3-Env1 Výš3-Obá1 + Pit3-Env2 Výš3-Obá2 + Pit3-LFO1 Výš3-LFO1 + Pit3-LFO2 Výš3-LFO2 + PW1-Env1 Pul1-Obá1 + PW1-Env2 Pul1-Obá2 + PW1-LFO1 Pul1-LFO1 + PW1-LFO2 Pul1-LFO2 + Sub3-Env1 Sub3-Obá1 + Sub3-Env2 Sub3-Obá2 + Sub3-LFO1 Sub3-LFO1 + Sub3-LFO2 Sub3-LFO2 + + Sine wave Sinusová vlna + Bandlimited Triangle wave Pásmově zúžená trojúhelníková vlna + Bandlimited Saw wave Pásmově zúžená pilovitá vlna + Bandlimited Ramp wave Pásmově zúžená šikmá vlna + Bandlimited Square wave Pásmově zúžená pravoúhlá vlna + Bandlimited Moog saw wave Pásmově zúžená pilovitá vlna typu Moog + + Soft square wave Zaoblená pravoúhlá vlna + Absolute sine wave Absolutní sinusová vlna + + Exponential wave Exponenciální vlna + White noise Bílý šum + Digital Triangle wave Digitální trojúhelníková vlna + Digital Saw wave Digitální pilovitá vlna + Digital Ramp wave Digitální šikmá vlna + Digital Square wave Digitální pravoúhlá vlna + Digital Moog saw wave Digitální pilovitá vlna typu Moog + Triangle wave Trojúhelníková vlna + Saw wave Pilovitá vlna + Ramp wave Šikmá vlna + Square wave Pravoúhlá vlna + Moog saw wave Pilovitá vlna typu Moog + Abs. sine wave Abs. sinusová vlna + Random Náhodná + Random smooth Vyhlazená náhodná @@ -4743,10 +5899,12 @@ Ujistěte se prosím, zda máte povolen zápis do souboru a do složky obsahují MonstroView + Operators view Zobrazení operátorů + The Operators view contains all the operators. These include both audible operators (oscillators) and inaudible operators, or modulators: Low-frequency oscillators and Envelopes. Knobs and other widgets in the Operators view have their own what's this -texts, so you can get more specific help for them that way. @@ -4755,10 +5913,12 @@ Knobs and other widgets in the Operators view have their own what's this -t Otočné ovladače a další ovládací prvky v Zobrazení operátorů mají své vlastní textové popisky, takže můžete získat bližší nápovědu, co který konkrétně dělá. + Matrix view Zobrazení matrice + The Matrix view contains the modulation matrix. Here you can define the modulation relationships between the various operators: Each audible operator (oscillators 1-3) has 3-4 properties that can be modulated by any of the modulators. Using more modulations consumes more CPU power. The view is divided to modulation targets, grouped by the target oscillator. Available targets are volume, pitch, phase, pulse width and sub-osc ratio. Note: some targets are specific to one oscillator only. @@ -4771,78 +5931,264 @@ Okno je rozděleno na cíle modulace, seskupené podle cílových oscilátorů. Každý cíl modulace má 4 otočné ovladače, jeden pro každý modulátor. Výchozí stav ovladačů je 0, tedy bez modulace. Otočení ovladače na 1 způsobí, že modulátor bude působit na cíl nejvíce, jak je možno. Otočení na -1 způsobí totéž, ale modulace bude inverzně obrácena. + + + + Volume + Hlasitost + + + + + + Panning + Panoráma + + + + + + Coarse detune + Hrubé rozladění + + + + + + semitones + půltónů + + + + + Finetune left + Jemné rozladění vlevo + + + + + + + cents + centů + + + + + Finetune right + Jemné rozladění vpravo + + + + + + Stereo phase offset + Posun stereo fáze + + + + + + + + deg + stupňů + + + + Pulse width + Délka pulzu + + + + Send sync on pulse rise + Synchronizace při nárůstu pulzu + + + + Send sync on pulse fall + Synchronizace při poklesu pulzu + + + + Hard sync oscillator 2 + Pevně synchronizovat oscilátor 2 + + + + Reverse sync oscillator 2 + Reverzně synchronizovat oscilátor 2 + + + + Sub-osc mix + Míchání sub-osc + + + + Hard sync oscillator 3 + Pevně synchronizovat oscilátor 3 + + + + Reverse sync oscillator 3 + Reverzně synchronizovat oscilátor 3 + + + + + + + Attack + Náběh + + + + + Rate + Typ + + + + + Phase + Fáze + + + + + Pre-delay + Předzpoždění + + + + + Hold + Držení + + + + + Decay + Pokles + + + + + Sustain + Držení + + + + + Release + Doznění + + + + + Slope + Strmost + + + Mix Osc2 with Osc3 Smíchat Osc2 a Osc3 + Modulate amplitude of Osc3 with Osc2 Modulovat amplitudu Osc3 pomocí Osc2 + Modulate frequency of Osc3 with Osc2 Modulovat frekvenci Osc3 pomocí Osc2 + Modulate phase of Osc3 with Osc2 Modulovat fázi Osc3 pomocí Osc2 + The CRS knob changes the tuning of oscillator 1 in semitone steps. Otočný ovladač CRS mění ladění oscilátoru 1 v půltónových krocích. + The CRS knob changes the tuning of oscillator 2 in semitone steps. Otočný ovladač CRS mění ladění oscilátoru 2 v půltónových krocích. + The CRS knob changes the tuning of oscillator 3 in semitone steps. Otočný ovladač CRS mění ladění oscilátoru 3 v půltónových krocích. + + + + FTL and FTR change the finetuning of the oscillator for left and right channels respectively. These can add stereo-detuning to the oscillator which widens the stereo image and causes an illusion of space. FTL a FTR změní jemné ladění oscilátoru pro levý a pravý kanál. To přidává oscilátoru stereo rozladění, které rozšíří stereo obraz a vytvoří dojem prostoru. + + + The SPO knob modifies the difference in phase between left and right channels. Higher difference creates a wider stereo image. Otočný ovladač SPO upravuje rozdíl ve fázi mezi levým a pravým kanálem. Větší rozdíl vytváří širší stereofonní obraz. + The PW knob controls the pulse width, also known as duty cycle, of oscillator 1. Oscillator 1 is a digital pulse wave oscillator, it doesn't produce bandlimited output, which means that you can use it as an audible oscillator but it will cause aliasing. You can also use it as an inaudible source of a sync signal, which can be used to synchronize oscillators 2 and 3. Otočný ovladač PW řídí šířku pulzu, jinak též pracovní cyklus, oscilátoru 1. Oscilátor 1 je digitální generátor pulzních vln, který nevytváří pásmově omezený výstup, což znamená, že jej sice můžete použít jako zdroj slyšitelného signálu, ale způsobuje aliasing. Můžete jej ale také využít jako neslyšitelný zdroj synchronizačního signálu, který může sloužit k synchronizaci oscilátorů 2 a 3. + Send Sync on Rise: When enabled, the Sync signal is sent every time the state of oscillator 1 changes from low to high, ie. when the amplitude changes from -1 to 1. Oscillator 1's pitch, phase and pulse width may affect the timing of syncs, but its volume has no effect on them. Sync signals are sent independently for both left and right channels. Zaslání synchronizačního signálu při nárůstu: je-li zapnuto, bude synchronizační signál zasílán pokaždé, když bude stav oscilátoru 1 změněn na vyšší, např. když se amplituda změní z -1 na 1. Výška, fáze a šířka pulzu oscilátoru 1 mohou mít vliv na časování synchronizace, ale jejich množství zde nemá žádný efekt. Synchronizační signály jsou odesílány nezávisle pro levý a pravý kanál. + Send Sync on Fall: When enabled, the Sync signal is sent every time the state of oscillator 1 changes from high to low, ie. when the amplitude changes from 1 to -1. Oscillator 1's pitch, phase and pulse width may affect the timing of syncs, but its volume has no effect on them. Sync signals are sent independently for both left and right channels. Zaslání synchronizačního signálu při poklesu: je-li zapnuto, bude synchronizační signál zasílán pokaždé, když bude stav oscilátoru 1 změněn na nižší, např. když se amplituda změní z 1 na -1. Výška, fáze a šířka pulzu oscilátoru 1 mohou mít vliv na časování synchronizace, ale jejich množství zde nemá žádný efekt. Synchronizační signály jsou odesílány nezávisle pro levý a pravý kanál. + + Hard sync: Every time the oscillator receives a sync signal from oscillator 1, its phase is reset to 0 + whatever its phase offset is. Pevná synchronizace: pokaždé, když oscilátor přijme synchronizační signál z oscilátoru 1, jeho fáze bude nastavena na 0, bez ohledu na jeho fázový posun. + + Reverse sync: Every time the oscillator receives a sync signal from oscillator 1, the amplitude of the oscillator gets inverted. Reverzní synchronizace: pokaždé, když oscilátor přijme synchronizační signál z oscilátoru 1, jeho amplituda bude převrácena. + Choose waveform for oscillator 2. Vyberte vlnu pro oscilátor 2. + Choose waveform for oscillator 3's first sub-osc. Oscillator 3 can smoothly interpolate between two different waveforms. Vyberte vlnu pro první suboscilátor oscilátoru 3. Oscilátor 3 může plynule interpolovat mezi dvěma různými vlnovými průběhy. + Choose waveform for oscillator 3's second sub-osc. Oscillator 3 can smoothly interpolate between two different waveforms. Vyberte vlnu pro druhý suboscilátor oscilátoru 3. Oscilátor 3 může plynule interpolovat mezi dvěma různými vlnovými průběhy. + The SUB knob changes the mixing ratio of the two sub-oscs of oscillator 3. Each sub-osc can be set to produce a different waveform, and oscillator 3 can smoothly interpolate between them. All incoming modulations to oscillator 3 are applied to both sub-oscs/waveforms in the exact same way. Otočný ovladač SUB mění poměr směšování mezi dvěma suboscilátory oscilátoru 3. Každý suboscilátor může být nastaven tak, aby vytvářel jiný vlnový průběh, a oscilátor 3 může plynule interpolovat mezi nimi. Všechny příchozí modulace oscilátoru 3 jsou shodným způsobem aplikovány na oba suboscilátory / vlnové průběhy. + In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. Mix mode means no modulation: the outputs of the oscillators are simply mixed together. @@ -4851,6 +6197,7 @@ Mix mode means no modulation: the outputs of the oscillators are simply mixed to Režim směšování znamená bez modulace: výstupy oscilátorů se jednoduše smíchají. + In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. AM means amplitude modulation: Oscillator 3's amplitude (volume) is modulated by oscillator 2. @@ -4859,6 +6206,7 @@ AM means amplitude modulation: Oscillator 3's amplitude (volume) is modulat AM znamená amplitudovou modulaci: Amplituda (hlasitost) oscilátoru 3 je modulována oscilátorem 2. + In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. FM means frequency modulation: Oscillator 3's frequency (pitch) is modulated by oscillator 2. The frequency modulation is implemented as phase modulation, which gives a more stable overall pitch than "pure" frequency modulation. @@ -4867,6 +6215,7 @@ FM means frequency modulation: Oscillator 3's frequency (pitch) is modulate FM znamená frekvenční modulaci: frekvence (výška) oscilátoru 3 je modulována oscilátorem 2. Frekvenční modulace je implementována jako fázová modulace, která poskytuje stabilnější výslednou výšku než "čistá" frekvenční modulace. + In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. PM means phase modulation: Oscillator 3's phase is modulated by oscillator 2. It differs from frequency modulation in that the phase changes are not cumulative. @@ -4875,162 +6224,124 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator PM znamená fázovou modulaci: fáze oscilátoru 3 je modulována oscilátorem 2. To se liší od frekvenční modulace tím, že fázové změny nejsou kumulativní. + Select the waveform for LFO 1. "Random" and "Random smooth" are special waveforms: they produce random output, where the rate of the LFO controls how often the state of the LFO changes. The smooth version interpolates between these states with cosine interpolation. These random modes can be used to give "life" to your presets - add some of that analog unpredictability... Vyberte tvar vlny pro LFO 1. "Náhodná" a "Vyhlazená náhodná" jsou speciální vlny: produkují náhodný výstup, kde rychlost LFO řídí, jak často se mění stav LFO. Vyhlazená verze interpoluje mezi těmito stavy kosinovou interpolací. Tyto náhodné režimy mohou být použity k oživení vašich předvoleb – přidávají něco z analogové nepředvídatelnosti... + Select the waveform for LFO 2. "Random" and "Random smooth" are special waveforms: they produce random output, where the rate of the LFO controls how often the state of the LFO changes. The smooth version interpolates between these states with cosine interpolation. These random modes can be used to give "life" to your presets - add some of that analog unpredictability... Vyberte tvar vlny pro LFO 2. "Náhodná" a "Vyhlazená náhodná" jsou speciální vlny: produkují náhodný výstup, kde rychlost LFO řídí, jak často se mění stav LFO. Vyhlazená verze interpoluje mezi těmito stavy kosinovou interpolací. Tyto náhodné režimy mohou být použity k oživení vašich předvoleb – přidávají něco z analogové nepředvídatelnosti... + + Attack causes the LFO to come on gradually from the start of the note. Náběh způsobí, že LFO najede postupně od začátku noty. + + Rate sets the speed of the LFO, measured in milliseconds per cycle. Can be synced to tempo. Rate nastavuje rychlost LFO, měřenou v milisekundách za cyklus. Lze synchronizovat s tempem. + + PHS controls the phase offset of the LFO. PHS řídí fázový posun LFO. + + PRE, or pre-delay, delays the start of the envelope from the start of the note. 0 means no delay. PRE nebo předzpoždění (PRE, predelay) zpozdí začátek obálky oproti začátku noty. Hodnota 0 znamená bez zpoždění. + + ATT, or attack, controls how fast the envelope ramps up at start, measured in milliseconds. A value of 0 means instant. NÁB nebo náběh určuje, jak rychle vystoupá začátek obálky do špičky, měřeno v milisekundách. Hodnota 0 znamená okamžitý náběh. + + HOLD controls how long the envelope stays at peak after the attack phase. Držení určuje, jak dlouho obálka zůstane na špičce po fázi náběhu. + + DEC, or decay, controls how fast the envelope falls off from its peak, measured in milliseconds it would take to go from peak to zero. The actual decay may be shorter if sustain is used. ÚTL nebo útlum (DEC, decoy) řídí rychlost poklesu obálky ze špičky do nulové úrovně (měřeno v milisekundách). Aktuální útlum může být kratší, pokud je použito podržení (sustain). + + SUS, or sustain, controls the sustain level of the envelope. The decay phase will not go below this level as long as the note is held. POD nebo podržení (SUS, sustain) řídí úroveň podržení v obálce. Fáze útlumu (decoy) nemůže jít pod tuto úroveň, dokud je nota držená. + + REL, or release, controls how long the release is for the note, measured in how long it would take to fall from peak to zero. Actual release may be shorter, depending on at what phase the note is released. UVO nebo uvolnění určuje, jak dlouhé bude ukončení noty, tedy jak dlouho bude trvat zeslabení ze špičky na nulu. Skutečná délka uvolnění může být kratší v závislosti na tom, ve které fázi je nota ukončena. + + The slope knob controls the curve or shape of the envelope. A value of 0 creates straight rises and falls. Negative values create curves that start slowly, peak quickly and fall of slowly again. Positive values create curves that start and end quickly, and stay longer near the peaks. Otočný ovladač sklon řídí křivku a tvar obálky. Hodnota 0 vytváří přímý nárůst i pokles. Záporné hodnoty vytvářejí křivku, která začíná pomalu, rychle dosáhne špičky a opět pomalu klesá. Pozitivní hodnoty vytvářejí křivku, která začíná a končí rychle a udržuje se v blízkosti špičky. - Volume - Hlasitost - - - Panning - Panoráma - - - Coarse detune - Hrubé rozladění - - - semitones - půltónů - - - Finetune left - Jemné rozladění vlevo - - - cents - centů - - - Finetune right - Jemné rozladění vpravo - - - Stereo phase offset - Posun stereo fáze - - - deg - stupňů - - - Pulse width - Délka pulzu - - - Send sync on pulse rise - Synchronizace při nárůstu pulzu - - - Send sync on pulse fall - Synchronizace při poklesu pulzu - - - Hard sync oscillator 2 - Pevně synchronizovat oscilátor 2 - - - Reverse sync oscillator 2 - Reverzně synchronizovat oscilátor 2 - - - Sub-osc mix - Míchání sub-osc - - - Hard sync oscillator 3 - Pevně synchronizovat oscilátor 3 - - - Reverse sync oscillator 3 - Reverzně synchronizovat oscilátor 3 - - - Attack - Náběh - - - Rate - Typ - - - Phase - Fáze - - - Pre-delay - Předzpoždění - - - Hold - Držení - - - Decay - Útlum - - - Sustain - Vydržení - - - Release - Uvolnění - - - Slope - Stoupání - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Modulation amount Hloubka modulace @@ -5038,34 +6349,42 @@ PM znamená fázovou modulaci: fáze oscilátoru 3 je modulována oscilátorem 2 MultitapEchoControlDialog + Length Délka + Step length: Délka kroku: + Dry Poměr + Dry Gain: Poměr zdrojového zvuku: + Stages Úrovně + Lowpass stages: Počet úrovní dolní propusti: + Swap inputs Přepnout vstupy + Swap left and right input channel for reflections Přepnout levý a pravý vstupní kanál pro odrazy @@ -5073,82 +6392,102 @@ PM znamená fázovou modulaci: fáze oscilátoru 3 je modulována oscilátorem 2 NesInstrument + Channel 1 Coarse detune Kanál 1 hrubé rozladění + Channel 1 Volume Hlasitost kanálu 1 + Channel 1 Envelope length Kanál 1 délka obálky + Channel 1 Duty cycle Kanál 1 pracovní cyklus + Channel 1 Sweep amount Kanál 1 množství sweepu + Channel 1 Sweep rate Kanál 1rychlost sweepu + Channel 2 Coarse detune Kanál 2 hrubé rozladění + Channel 2 Volume Hlasitost kanálu 2 + Channel 2 Envelope length Kanál 2 délka obálky + Channel 2 Duty cycle Kanál 2 pracovní cyklus + Channel 2 Sweep amount Kanál 2 množství sweepu + Channel 2 Sweep rate Kanál 2 rychlost sweepu + Channel 3 Coarse detune Kanál 3 hrubé rozladění + Channel 3 Volume Hlasitost kanálu 3 + Channel 4 Volume Hlasitost kanálu 4 + Channel 4 Envelope length Kanál 4 délka obálky + Channel 4 Noise frequency Kanál 4 frekvence šumu + Channel 4 Noise frequency sweep Kanál 4 sweep frekvence šumu + Master volume Hlavní hlasitost + Vibrato Vibráto @@ -5156,114 +6495,155 @@ PM znamená fázovou modulaci: fáze oscilátoru 3 je modulována oscilátorem 2 NesInstrumentView + + + + Volume Hlasitost + + + Coarse detune Hrubé rozladění + + + Envelope length Délka obálky + Enable channel 1 Zapnout kanál 1 + Enable envelope 1 Zapnout obálku 1 + Enable envelope 1 loop Zapnout smyčku obálky 1 + Enable sweep 1 Zapnout sweep 1 + + Sweep amount Množství sweepu + + Sweep rate Rychlost sweepu + + 12.5% Duty cycle 12.5% pracovního cyklu + + 25% Duty cycle 25% pracovního cyklu + + 50% Duty cycle 50% pracovního cyklu + + 75% Duty cycle 75% pracovního cyklu + Enable channel 2 Zapnout kanál 2 + Enable envelope 2 Zapnout obálku 2 + Enable envelope 2 loop Zapnout smyčku obálky 2 + Enable sweep 2 Zapnout sweep 2 + Enable channel 3 Zapnout kanál 3 + Noise Frequency Frekvence šumu + Frequency sweep Frekvence sweepu + Enable channel 4 Zapnout kanál 4 + Enable envelope 4 Zapnout obálku 4 + Enable envelope 4 loop Zapnout smyčku obálky 4 + Quantize noise frequency when using note frequency Kvantizovat frekvenci šumu při použití frekvence noty + Use note frequency for noise Použít frekvenci pro šum + Noise mode Typ šumu + Master Volume Hlavní hlasitost + Vibrato Vibráto @@ -5271,81 +6651,103 @@ PM znamená fázovou modulaci: fáze oscilátoru 3 je modulována oscilátorem 2 OscillatorObject - Osc %1 volume - Osc %1 hlasitost - - - Osc %1 panning - Osc %1 panoráma - - - Osc %1 coarse detuning - Osc %1 hrubé rozladění - - - Osc %1 fine detuning left - Osc %1 jemné rozladění vlevo - - - Osc %1 fine detuning right - Osc %1 jemné rozladění vpravo - - - Osc %1 phase-offset - Osc %1 posun fáze - - - Osc %1 stereo phase-detuning - Osc %1 rozladění stereo fáze - - - Osc %1 wave shape - Osc %1 forma vlny - - - Modulation type %1 - Typ modulace %1 - - + Osc %1 waveform Osc %1 vlna + Osc %1 harmonic Osc %1 harmonické + + + + Osc %1 volume + Osc %1 hlasitost + + + + + Osc %1 panning + Osc %1 panoráma + + + + + Osc %1 fine detuning left + Osc %1 jemné rozladění vlevo + + + + Osc %1 coarse detuning + Osc %1 hrubé rozladění + + + + Osc %1 fine detuning right + Osc %1 jemné rozladění vpravo + + + + Osc %1 phase-offset + Osc %1 posun fáze + + + + Osc %1 stereo phase-detuning + Osc %1 rozladění stereo fáze + + + + Osc %1 wave shape + Osc %1 forma vlny + + + + Modulation type %1 + Typ modulace %1 + PatchesDialog + Qsynth: Channel Preset Qsynth: Předvolba kanálu + Bank selector Výběr banky + Bank Banka + Program selector Výběr programu + Patch Patch + Name Název + OK OK + Cancel Zrušit @@ -5353,46 +6755,57 @@ PM znamená fázovou modulaci: fáze oscilátoru 3 je modulována oscilátorem 2 PatmanView + Open other patch Otevřít jiný patch + Click here to open another patch-file. Loop and Tune settings are not reset. Klepněte sem, pokud chcete otevřít další patch-soubor. Nastavení smyčky a režimu ladění zůstanou zachována. + Loop Smyčka + Loop mode Režim smyčky + Here you can toggle the Loop mode. If enabled, PatMan will use the loop information available in the file. Zde můžete přepínat režim smyčky. Je-li zapnutá, PatMan použije informace o smyčce dostupné v souboru. + Tune Ladění + Tune mode Režim ladění + Here you can toggle the Tune mode. If enabled, PatMan will tune the sample to match the note's frequency. Zde můžete přepínat režim ladění. Je-li zapnut, PatMan naladí vzorek tak, aby odpovídal frekvenci noty. + No file selected Není vybrán žádný soubor + Open patch file Otevřít soubor patch + Patch-Files (*.pat) Soubor patch (*.pat) @@ -5400,30 +6813,47 @@ PM znamená fázovou modulaci: fáze oscilátoru 3 je modulována oscilátorem 2 PatternView + + use mouse wheel to set velocity of a step + použijte kolečko myši pro nastavení dynamiky kroku + + + + double-click to open in Piano Roll + poklepáním otevřete v Piano rollu + + + Open in piano-roll Otevřít v Piano rollu + Clear all notes Vymazat všechny noty + Reset name Resetovat jméno + Change name Změnit jméno + Add steps Přidat kroky + Remove steps Odstranit kroky + Clone Steps Klonovat kroky @@ -5431,25 +6861,30 @@ PM znamená fázovou modulaci: fáze oscilátoru 3 je modulována oscilátorem 2 PeakController + Peak Controller - Řízení špičky + Ovladač špičky + Peak Controller Bug - Chyba řízení špičky + Chyba ovladače špičky + Due to a bug in older version of LMMS, the peak controllers may not be connect properly. Please ensure that peak controllers are connected properly and re-save this file. Sorry for any inconvenience caused. - Z důvodu chyby ve starší verzi LMMS nemusí být řízení špičky správně připojeno. Ujistěte se prosím, zda je řízení špičky správně připojeno a znovu uložte tento soubor. Omlouváme se za způsobené nepříjemnosti. + Z důvodu chyby ve starší verzi LMMS nemusí být ovladače špiček správně připojeny. Ujistěte se prosím, zda jsou ovladače špiček správně připojeny a znovu uložte tento soubor. Omlouváme se za způsobené nepříjemnosti. PeakControllerDialog + PEAK ŠPIČ + LFO Controller Ovladač LFO @@ -5457,306 +6892,382 @@ PM znamená fázovou modulaci: fáze oscilátoru 3 je modulována oscilátorem 2 PeakControllerEffectControlDialog + BASE ZÁKL + Base amount: Základní míra: - Modulation amount: - Hloubka modulace: - - - Attack: - Náběh: - - - Release: - Uvolnění: - - + AMNT MNOŽ + + Modulation amount: + Hloubka modulace: + + + MULT NÁSB + Amount Multiplicator: Násobič množství: + ATCK NÁBH + + Attack: + Náběh: + + + DCAY - ÚTLM + POKL - Treshold: - Práh: + + Release: + Doznění: + TRSH PRÁH + + + Treshold: + Práh: + PeakControllerEffectControls + Base value Základní hodnota + Modulation amount Hloubka modulace - Mute output - Ztlumit výstup - - + Attack Náběh + Release - Uvolnění + Doznění + + Treshold + Práh + + + + Mute output + Ztlumit výstup + + + Abs Value Abs hodnota + Amount Multiplicator Násobič množství - - Treshold - Práh - PianoRoll - Please open a pattern by double-clicking on it! - Otevřete prosím pattern poklepáním! - - - Last note - Podle poslední noty - - - Note lock - Zamknout notu - - + Note Velocity Dynamika noty + Note Panning Panoráma noty + Mark/unmark current semitone Zvýraznit/Skrýt zvolený tón - Mark current scale - Zvýraznit zvolenou stupnici - - - Mark current chord - Zvýraznit zvolený akord - - - Unmark all - Skrýt vše - - - No scale - Žádná stupnice - - - No chord - Žádný akord - - - Velocity: %1% - Dynamika: %1% - - - Panning: %1% left - Panoráma: %1% vlevo - - - Panning: %1% right - Panoráma: %1% vpravo - - - Panning: center - Panoráma: střed - - - Please enter a new value between %1 and %2: - Vložte prosím novou hodnotu mezi %1 a %2: - - + Mark/unmark all corresponding octave semitones Zvýraznit/Skrýt zvolený tón ve všech oktávách + + Mark current scale + Zvýraznit zvolenou stupnici + + + + Mark current chord + Zvýraznit zvolený akord + + + + Unmark all + Skrýt vše + + + Select all notes on this key Vybrat všechny noty zvolené výšky + + + Note lock + Zamknout notu + + + + Last note + Podle poslední noty + + + + No scale + Žádná stupnice + + + + No chord + Žádný akord + + + + Velocity: %1% + Dynamika: %1% + + + + Panning: %1% left + Panoráma: %1% vlevo + + + + Panning: %1% right + Panoráma: %1% vpravo + + + + Panning: center + Panoráma: střed + + + + Please open a pattern by double-clicking on it! + Otevřete prosím záznam poklepáním! + + + + + Please enter a new value between %1 and %2: + Vložte prosím novou hodnotu mezi %1 a %2: + PianoRollWindow + Play/pause current pattern (Space) - Přehrát/Pozastavit přehrávání aktuálního patternu (mezerník) + Přehrát/Pozastavit přehrávání aktuálního záznamu (mezerník) + Record notes from MIDI-device/channel-piano Nahrávat z MIDI zařízení / virtuální klávesnice + Record notes from MIDI-device/channel-piano while playing song or BB track Nahrávat z MIDI zařízení / virtuální klávesnice při přehrávání skladby nebo stopy bicích/basů + Stop playing of current pattern (Space) - Zastavit přehrávání aktuálního patternu (mezerník) + Zastavit přehrávání aktuálního záznamu (mezerník) + Click here to play the current pattern. This is useful while editing it. The pattern is automatically looped when its end is reached. - Klepněte sem, pokud chcete přehrát aktuální pattern. To je užitečné při editaci. Pattern je automaticky přehráván ve smyčce. + Klepněte sem, pokud chcete přehrát aktuální záznam. To je užitečné při editaci. Záznam je automaticky přehráván ve smyčce. + Click here to record notes from a MIDI-device or the virtual test-piano of the according channel-window to the current pattern. When recording all notes you play will be written to this pattern and you can play and edit them afterwards. - Klepněte sem, pokud chcete nahrávat z MIDI zařízení nebo z virtuální klávesnice příslušného kanálového okna do aktuálního patternu. Při nahrávání se zaznamenají všechny zahrané noty do tohoto patternu, a následně je můžete přehrát nebo upravit. + Klepněte sem, pokud chcete nahrávat z MIDI zařízení nebo z virtuální klávesnice příslušného kanálového okna do aktuálního záznamu. Při nahrávání se zapíší všechny zahrané noty do tohoto záznamu, a následně je můžete přehrát nebo upravit. + Click here to record notes from a MIDI-device or the virtual test-piano of the according channel-window to the current pattern. When recording all notes you play will be written to this pattern and you will hear the song or BB track in the background. - Klepněte sem, pokud chcete nahrávat z MIDI zařízení nebo z virtuální klávesnice příslušného kanálového okna do aktuálního patternu. Při nahrávání se zaznamenají všechny zahrané noty do tohoto patternu a na pozadí uslyšíte skladbu nebo BB stopu. + Klepněte sem, pokud chcete nahrávat z MIDI zařízení nebo z virtuální klávesnice příslušného kanálového okna do aktuálního záznamu. Při nahrávání se zapíší všechny zahrané noty do tohoto záznamu a na pozadí uslyšíte skladbu nebo stopu bicích/basů. + Click here to stop playback of current pattern. - Klepněte sem, pokud chcete zastavit přehrávání aktuálního patternu. - - - Draw mode (Shift+D) - Režim kreslení (Shift+D) - - - Erase mode (Shift+E) - Režim mazání (Shift+E) - - - Select mode (Shift+S) - Režim výběru (Shift+S) - - - Detune mode (Shift+T) - Režim rozladění (Shift+T) - - - Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold %1 to temporarily go into select mode. - Klepněte sem pro aktivaci režimu kreslení. V tomto režimu můžete přidávat, měnit a přesouvat noty. Toto je výchozí režim, který se používá nejčastěji. Pro aktivaci tohoto režimu můžete také stisknout "Shift+D" na klávesnici. V tomto režimu podržte %1 pro dočasné přepnutí do režimu výběru. - - - Click here and erase mode will be activated. In this mode you can erase notes. You can also press 'Shift+E' on your keyboard to activate this mode. - Klepněte sem pro aktivaci režimu mazání. V tomto režimu můžete vymazávat noty. Pro aktivaci tohoto režimu můžete také stisknout tlačítko "Shift+E" na klávesnici. - - - Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold %1 in draw mode to temporarily use select mode. - Klepněte sem pro aktivaci režimu výběru. V tomto režimu můžete vybírat noty. Alternativně můžete v režimu kreslení držet %1 pro dočasné přepnutí do režimu výběru. - - - Click here and detune mode will be activated. In this mode you can click a note to open its automation detuning. You can utilize this to slide notes from one to another. You can also press 'Shift+T' on your keyboard to activate this mode. - Klepněte sem pro aktivaci režimu rozladění. V tomto režimu můžete klepnutím na notu otevřít její automatické rozladění. To můžete využít ke sklouznutí z jedné noty na jinou. Pro aktivaci tohoto režimu můžete také stisknout klávesu "Shift+T" na klávesnici. - - - Cut selected notes (%1+X) - Vyjmout označené noty (%1+X) - - - Copy selected notes (%1+C) - Kopírovat označené noty (%1+C) - - - Paste notes from clipboard (%1+V) - Vložit noty ze schránky (%1+V) - - - Click here and the selected notes will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. - Klepněte sem, pokud chcete označené noty vyjmout a uložit do schránky. Vložit je pak můžete kdekoliv v libovolném patternu pomocí tlačítka Vložit. - - - Click here and the selected notes will be copied into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. - Klepněte sem, pokud chcete označené noty zkopírovat do schránky. Vložit je pak můžete kdekoliv v libovolného patternu pomocí tlačítka Vložit. - - - Click here and the notes from the clipboard will be pasted at the first visible measure. - Klepnete-li sem, budou noty ze schránky vloženy do prvního viditelného taktu. - - - This controls the magnification of an axis. It can be helpful to choose magnification for a specific task. For ordinary editing, the magnification should be fitted to your smallest notes. - Tímto se ovládá zvětšení osy. To může být užitečné při volbě zvětšení pro konkrétní úkol. Při běžné úpravě by mělo být zvětšení použito na vaše nejmenší noty. - - - The 'Q' stands for quantization, and controls the grid size notes and control points snap to. With smaller quantization values, you can draw shorter notes in Piano Roll, and more exact control points in the Automation Editor. - "Q" znamená kvantizaci, která ovládá mřížku velikosti not a kontrolní body krokování. S menšími hodnotami kvantizace můžete kreslit kratší noty v Piano rollu a přesnější kontrolní body v editoru automatizace. - - - This lets you select the length of new notes. 'Last Note' means that LMMS will use the note length of the note you last edited - Tímto je možno vybrat délku nových not. "Poslední nota" znamená, že LMMS použije délku naposledy upravované noty. - - - The feature is directly connected to the context-menu on the virtual keyboard, to the left in Piano Roll. After you have chosen the scale you want in this drop-down menu, you can right click on a desired key in the virtual keyboard, and then choose 'Mark current Scale'. LMMS will highlight all notes that belongs to the chosen scale, and in the key you have selected! - Funkce je přímo propojena s kontextovou nabídkou na virtuální klávesnici vlevo v Piano rollu. Poté, co jste v rozbalovací nabídce zvolili stupnici, můžete klepnout pravým tlačítkem na požadovanou klávesu na virtuální klávesnici, a pak zvolit "Zvýraznit zvolenou stupnici". LMMS zvýrazní všechny noty, které patří do zvolené stupnice, a to od klávesy, kterou jste vybrali! - - - Let you select a chord which LMMS then can draw or highlight.You can find the most common chords in this drop-down menu. After you have selected a chord, click anywhere to place the chord, and right click on the virtual keyboard to open context menu and highlight the chord. To return to single note placement, you need to choose 'No chord' in this drop-down menu. - Vyberte si akord, který pak LMMS může nakreslit nebo zvýraznit. V rozbalovací nabídce najdete nejčastěji používané akordy. Po výběru akordu klepněte kamkoliv pro umístění akordu, klepnutím pravým tlačítkem na virtuální klávesnici pak otevřete kontextové menu a zvýrazníte akord. Chcete-li se vrátit k práci s jednotlivými notami, musíte v rozbalovací nabídce zvolit možnost "Žádný akord". + Klepněte sem, pokud chcete zastavit přehrávání aktuálního záznamu. + Edit actions Akce úprav + + Draw mode (Shift+D) + Režim kreslení (Shift+D) + + + + Erase mode (Shift+E) + Režim mazání (Shift+E) + + + + Select mode (Shift+S) + Režim výběru (Shift+S) + + + + Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold %1 to temporarily go into select mode. + Klepněte sem pro aktivaci režimu kreslení. V tomto režimu můžete přidávat, měnit a přesouvat noty. Toto je výchozí režim, který se používá nejčastěji. Pro aktivaci tohoto režimu můžete také stisknout "Shift+D" na klávesnici. V tomto režimu podržte %1 pro dočasné přepnutí do režimu výběru. + + + + Click here and erase mode will be activated. In this mode you can erase notes. You can also press 'Shift+E' on your keyboard to activate this mode. + Klepněte sem pro aktivaci režimu mazání. V tomto režimu můžete vymazávat noty. Pro aktivaci tohoto režimu můžete také stisknout tlačítko "Shift+E" na klávesnici. + + + + Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold %1 in draw mode to temporarily use select mode. + Klepněte sem pro aktivaci režimu výběru. V tomto režimu můžete vybírat noty. Alternativně můžete v režimu kreslení držet %1 pro dočasné přepnutí do režimu výběru. + + + + Pitch Bend mode (Shift+T) + Režim ohýbání výšky (Shift+T) + + + + Click here and Pitch Bend mode will be activated. In this mode you can click a note to open its automation detuning. You can utilize this to slide notes from one to another. You can also press 'Shift+T' on your keyboard to activate this mode. + Klepněte sem pro aktivaci režimu ohýbání výšky tónu. V tomto režimu můžete klepnutím na notu otevřít její automatizované rozladění. To můžete využít ke sklouznutí z jedné noty na jinou. Pro aktivaci tohoto režimu můžete také stisknout klávesu "Shift+T" na klávesnici. + + + + Quantize + Kvantizace + + + Copy paste controls Ovládání kopírování a vkládání + + Cut selected notes (%1+X) + Vyjmout označené noty (%1+X) + + + + Copy selected notes (%1+C) + Kopírovat označené noty (%1+C) + + + + Paste notes from clipboard (%1+V) + Vložit noty ze schránky (%1+V) + + + + Click here and the selected notes will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. + Klepněte sem, pokud chcete označené noty vyjmout a uložit do schránky. Vložit je pak můžete kdekoliv v libovolném záznamu pomocí tlačítka Vložit. + + + + Click here and the selected notes will be copied into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. + Klepněte sem, pokud chcete označené noty zkopírovat do schránky. Vložit je pak můžete kdekoliv v libovolném záznamu pomocí tlačítka Vložit. + + + + Click here and the notes from the clipboard will be pasted at the first visible measure. + Klepnete-li sem, budou noty ze schránky vloženy do prvního viditelného taktu. + + + Timeline controls Ovládání časové osy + Zoom and note controls Lupa a ovládání not + + This controls the magnification of an axis. It can be helpful to choose magnification for a specific task. For ordinary editing, the magnification should be fitted to your smallest notes. + Tímto se ovládá zvětšení osy. To může být užitečné při volbě zvětšení pro konkrétní úkol. Při běžné úpravě by mělo být zvětšení použito na vaše nejmenší noty. + + + + The 'Q' stands for quantization, and controls the grid size notes and control points snap to. With smaller quantization values, you can draw shorter notes in Piano Roll, and more exact control points in the Automation Editor. + "Q" znamená kvantizaci, která ovládá mřížku velikosti not a kontrolní body krokování. S menšími hodnotami kvantizace můžete kreslit kratší noty v Piano rollu a přesnější kontrolní body v editoru automatizace. + + + + This lets you select the length of new notes. 'Last Note' means that LMMS will use the note length of the note you last edited + Tímto je možno vybrat délku nových not. "Poslední nota" znamená, že LMMS použije délku naposledy upravované noty. + + + + The feature is directly connected to the context-menu on the virtual keyboard, to the left in Piano Roll. After you have chosen the scale you want in this drop-down menu, you can right click on a desired key in the virtual keyboard, and then choose 'Mark current Scale'. LMMS will highlight all notes that belongs to the chosen scale, and in the key you have selected! + Funkce je přímo propojena s kontextovou nabídkou na virtuální klávesnici vlevo v Piano rollu. Poté, co jste v rozbalovací nabídce zvolili stupnici, můžete klepnout pravým tlačítkem na požadovanou klávesu na virtuální klávesnici, a pak zvolit "Zvýraznit zvolenou stupnici". LMMS zvýrazní všechny noty, které patří do zvolené stupnice, a to od klávesy, kterou jste vybrali! + + + + Let you select a chord which LMMS then can draw or highlight.You can find the most common chords in this drop-down menu. After you have selected a chord, click anywhere to place the chord, and right click on the virtual keyboard to open context menu and highlight the chord. To return to single note placement, you need to choose 'No chord' in this drop-down menu. + Vyberte si akord, který pak LMMS může nakreslit nebo zvýraznit. V rozbalovací nabídce najdete nejčastěji používané akordy. Po výběru akordu klepněte kamkoliv pro umístění akordu, klepnutím pravým tlačítkem na virtuální klávesnici pak otevřete kontextové menu a zvýrazníte akord. Chcete-li se vrátit k práci s jednotlivými notami, musíte v rozbalovací nabídce zvolit možnost "Žádný akord". + + + + Piano-Roll - %1 Piano roll – %1 + + Piano-Roll - no pattern - Piano roll – žádný pattern - - - Quantize - Kvantizace + Piano roll – žádný záznam PianoView + Base note Základní nota @@ -5764,20 +7275,24 @@ PM znamená fázovou modulaci: fáze oscilátoru 3 je modulována oscilátorem 2 Plugin + Plugin not found Plugin nenalezen + The plugin "%1" wasn't found or could not be loaded! Reason: "%2" Plugin "%1" nebyl nalezen nebo nemůže být načten! Důvod: "%2" + Error while loading plugin Při načítání pluginu došlo k chybě + Failed to load plugin "%1"! Načtení pluginu "%1" selhalo! @@ -5785,25 +7300,30 @@ Důvod: "%2" PluginBrowser + + Instrument Plugins + Nástrojové pluginy + + + Instrument browser Prohlížeč nástrojů + Drag an instrument into either the Song-Editor, the Beat+Bassline Editor or into an existing instrument track. Nástroj přetáhněte do editoru skladby, editoru bicích/basů nebo do existující nástrojové stopy. - - Instrument Plugins - Nástrojové pluginy - PluginFactory + Plugin not found. Plugin nebyl nalezen. + LMMS plugin %1 does not have a plugin descriptor named %2! U LMMS pluginu %1 chybí popisovač pluginu s názvem %2! @@ -5811,129 +7331,160 @@ Důvod: "%2" ProjectNotes - Edit Actions - Provedené úpravy - - - &Undo - &Zpět - - - %1+Z - %1+Z - - - &Redo - &Znovu - - - %1+Y - %1+Z - - - &Copy - &Kopírovat - - - %1+C - %1+C - - - Cu&t - &Vyjmout - - - %1+X - %1+X - - - &Paste - V&ložit - - - %1+V - %1+V - - - Format Actions - Formátování - - - &Bold - &Tučné - - - %1+B - %1+B - - - &Italic - &Kurzíva - - - %1+I - %1+I - - - &Underline - &Podtržené - - - %1+U - %1+U - - - &Left - &Vlevo - - - %1+L - %1+L - - - C&enter - &Na střed - - - %1+E - %1+E - - - &Right - V&pravo - - - %1+R - %1+R - - - &Justify - &Do bloku - - - %1+J - %1+J - - - &Color... - &Barva... - - + Project Notes Poznámky k projektu + Enter project notes here Sem zapište poznámky k projektu + + + Edit Actions + Provedené úpravy + + + + &Undo + &Zpět + + + + %1+Z + %1+Z + + + + &Redo + &Znovu + + + + %1+Y + %1+Z + + + + &Copy + &Kopírovat + + + + %1+C + %1+C + + + + Cu&t + &Vyjmout + + + + %1+X + %1+X + + + + &Paste + V&ložit + + + + %1+V + %1+V + + + + Format Actions + Formátování + + + + &Bold + &Tučné + + + + %1+B + %1+B + + + + &Italic + &Kurzíva + + + + %1+I + %1+I + + + + &Underline + &Podtržené + + + + %1+U + %1+U + + + + &Left + &Vlevo + + + + %1+L + %1+L + + + + C&enter + &Na střed + + + + %1+E + %1+E + + + + &Right + V&pravo + + + + %1+R + %1+R + + + + &Justify + &Do bloku + + + + %1+J + %1+J + + + + &Color... + &Barva... + ProjectRenderer + WAV-File (*.wav) WAV soubor (*.wav) + Compressed OGG-File (*.ogg) Komprimovaný OGG soubor (*.ogg) @@ -5942,6 +7493,7 @@ Důvod: "%2" Soubor FLAC (*.flac) + Compressed MP3-File (*.mp3) Komprimovaný soubor MP3 (*.mp3) @@ -5949,57 +7501,89 @@ Důvod: "%2" QWidget + + + Name: Název: + + Maker: Tvůrce: + + Copyright: Autorská práva: + + Requires Real Time: Vyžaduje běh v reálném čase: + + + + + + Yes Ano + + + + + + No Ne + + Real Time Capable: Schopnost běhu v reálném čase: + + In Place Broken: Na místě poškozeného: + + Channels In: Vstupní kanály: + + Channels Out: Výstupní kanály: - File: - Soubor: - - + File: %1 Soubor: %1 + + + File: + Soubor: + RenameDialog + Rename... Přejmenovat... @@ -6007,34 +7591,42 @@ Důvod: "%2" ReverbSCControlDialog + Input Vstup + Input Gain: Zesílení vstupu: + Size Velikost + Size: Velikost: + Color Barva + Color: Barva: + Output Výstup + Output Gain: Zesílení výstupu: @@ -6042,18 +7634,22 @@ Důvod: "%2" ReverbSCControls + Input Gain Vstupní úroveň + Size Velikost + Color Barva + Output Gain Zesílení výstupu @@ -6061,81 +7657,100 @@ Důvod: "%2" SampleBuffer - Open audio file - Otevřít audio soubor - - - Wave-Files (*.wav) - WAV soubory (*.wav) - - - OGG-Files (*.ogg) - OGG soubory (*.ogg) - - - DrumSynth-Files (*.ds) - DrumSynth soubory (*.ds) - - - FLAC-Files (*.flac) - FLAC soubory (*.flac) - - - SPEEX-Files (*.spx) - SPEEX soubory (*.spx) - - - VOC-Files (*.voc) - VOC soubory (*.voc) - - - AIFF-Files (*.aif *.aiff) - Soubory AIFF (*.aif *.aiff) - - - AU-Files (*.au) - AU soubory (*.au) - - - RAW-Files (*.raw) - RAW soubory (*.raw) - - - All Audio-Files (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw) - Všechny audio soubory (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw) - - + Fail to open file Chyba otevírání souboru + Audio files are limited to %1 MB in size and %2 minutes of playing time Audio soubory jsou omezeny na %1 MB velikosti a %2 minut délky + + + Open audio file + Otevřít audio soubor + + + + All Audio-Files (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw) + Všechny audio soubory (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw) + + + + Wave-Files (*.wav) + WAV soubory (*.wav) + + + + OGG-Files (*.ogg) + OGG soubory (*.ogg) + + + + DrumSynth-Files (*.ds) + DrumSynth soubory (*.ds) + + + + FLAC-Files (*.flac) + FLAC soubory (*.flac) + + + + SPEEX-Files (*.spx) + SPEEX soubory (*.spx) + + + + VOC-Files (*.voc) + VOC soubory (*.voc) + + + + AIFF-Files (*.aif *.aiff) + Soubory AIFF (*.aif *.aiff) + + + + AU-Files (*.au) + AU soubory (*.au) + + + + RAW-Files (*.raw) + RAW soubory (*.raw) + SampleTCOView + double-click to select sample poklepáním vyberte sampl + Delete (middle mousebutton) Smazat (prostřední tlačítko myši) + Cut Vyjmout + Copy Kopírovat + Paste Vložit + Mute/unmute (<%1> + middle click) Ztlumit/Odtlumit (<%1> + prostřední tlačítko) @@ -6143,41 +7758,51 @@ Důvod: "%2" SampleTrack - Sample track - Stopa samplů - - + Volume Hlasitost + Panning Panoráma + + + + Sample track + Stopa samplů + SampleTrackView + Track volume Hlasitost stopy + Channel volume: Hlasitost kanálu: + VOL HLA + Panning Panoráma + Panning: Panoráma: + PAN PAN @@ -6185,497 +7810,659 @@ Důvod: "%2" SetupDialog + Setup LMMS Nastavení LMMS + + General settings Hlavní nastavení + BUFFER SIZE VELIKOST VYR. PAMĚTI + + Reset to default-value Nastavit výchozí hodnoty + MISC JINÉ + Enable tooltips Zapnout bublinovou nápovědu + Show restart warning after changing settings Zobrazit výzvu k restartu po změně nastavení + + Display volume as dBFS + Zobrazit hlasitost v dBFS + + + Compress project files per default Komprimovat soubory s projekty + One instrument track window mode Režim jedné stopy pro nástroje + HQ-mode for output audio-device HQ režim pro výstup audio zařízení + Compact track buttons Malá tlačítka u stop + Sync VST plugins to host playback Synchronizace VST pluginů s hostujícím přehráváním + Enable note labels in piano roll Povolit názvy tónů v Piano rollu + Enable waveform display by default Povolit zobrazení vlny ve výchozím nastavení + Keep effects running even without input Nechat efekty spuštěné i bez vstupu + Create backup file when saving a project Při ukládání projektu vytvořit záložní soubor + + Reopen last project on start + Po spuštění otevřít poslední projekt + + + + Use built-in NaN handler + Použít vestavěný NaN handler + + + + PLUGIN EMBEDDING + VLOŽENÍ PLUGINU + + + + No embedding + Nevkládat + + + + Embed using Qt API + Vložit pomocí rozhraní Qt + + + + Embed using native Win32 API + Vložit pomocí nativního rozhraní Win32 + + + + Embed using XEmbed protocol + Vložit pomocí protokolu XEmbed + + + LANGUAGE Jazyk + + Paths Cesty + + Directories + Adresáře + + + LMMS working directory Pracovní adresář LMMS - VST-plugin directory - Adresář pro VST pluginy + + Themes directory + Adresář pro témata + Background artwork Obrázek na pozadí + + VST-plugin directory + Adresář pro VST pluginy + + + + GIG directory + Adresář pro GIG + + + + SF2 directory + Adresář pro SF2 + + + + LADSPA plugin directories + Adresář pro LADSPA pluginy + + + STK rawwave directory Adresář pro STK rawwave + Default Soundfont File Výchozí Soundfont soubor + + Performance settings Nastavení výkonu + + Auto save + Automatické ukládání + + + + Enable auto-save + Povolit automatické ukládání + + + + Allow auto-save while playing + Povolit automatické ukládání během přehrávání + + + UI effects vs. performance Efekty uživatelského rozhraní vs. výkon + Smooth scroll in Song Editor Plynulé posouvání v Song Editoru + Show playback cursor in AudioFileProcessor Zobrazit přehrávací kurzor v AudioFileProcessoru + + Audio settings Audio nastavení + AUDIO INTERFACE AUDIO ROZHRANÍ + + MIDI settings MIDI nastavení + MIDI INTERFACE MIDI ROZHRANÍ + OK OK + Cancel Zrušit + Restart LMMS Restartovat LMMS + Please note that most changes won't take effect until you restart LMMS! Mnohé změny nastavení se projeví až po restartu LMMS! + Frames: %1 Latency: %2 ms Rámce: %1 Zpoždění %2 ms + Here you can setup the internal buffer-size used by LMMS. Smaller values result in a lower latency but also may cause unusable sound or bad performance, especially on older computers or systems with a non-realtime kernel. Zde můžete nastavit interní velikost vyrovnávací paměti, která je užívána LMMS. Nízké hodnoty vedou k menšímu zpoždění, ale také způsobují nepoužitelný zvuk nebo špatný výkon, zejména na starých počítačích či systémech s jádrem nepodporujícím real time. + Choose LMMS working directory Vyberte pracovní adresář LMMS - Choose your VST-plugin directory - Vyberte adresář pro VST pluginy - - - Choose artwork-theme directory - Vyberte adresář s tématy - - - Choose LADSPA plugin directory - Vyberte adresář pro LADSPA pluginy - - - Choose STK rawwave directory - Vyberte adresář pro STK rawwave - - - Choose default SoundFont - Vyberte výchozí SoundFont - - - Choose background artwork - Vyberte obrázek na pozadí - - - Here you can select your preferred audio-interface. Depending on the configuration of your system during compilation time you can choose between ALSA, JACK, OSS and more. Below you see a box which offers controls to setup the selected audio-interface. - Zde vyberte preferované audio rozhraní. V závislosti na konfiguraci Vašeho systému při kompilaci můžete volit mezi ALSA, JACK, OSS a dalšími. Níže vidíte políčko, které nabízí možnost nastavení vybraného audio rozhraní. - - - Here you can select your preferred MIDI-interface. Depending on the configuration of your system during compilation time you can choose between ALSA, OSS and more. Below you see a box which offers controls to setup the selected MIDI-interface. - Zde vyberte preferované MIDI rozhraní. V závislosti na konfiguraci Vašeho systému při kompilaci můžete volit mezi ALSA OSS a dalšími. Níže vidíte políčko, které nabízí možnost nastavení vybraného MIDI rozhraní. - - - Reopen last project on start - Po spuštění otevřít poslední projekt - - - Directories - Adresáře - - - Themes directory - Adresář pro témata - - - GIG directory - Adresář pro GIG - - - SF2 directory - Adresář pro SF2 - - - LADSPA plugin directories - Adresář pro LADSPA pluginy - - - Auto save - Automatické ukládání - - + Choose your GIG directory Vyberte svůj adresář pro GIG soubory + Choose your SF2 directory Vyberte svůj adresář pro SF2 soubory + + Choose your VST-plugin directory + Vyberte adresář pro VST pluginy + + + + Choose artwork-theme directory + Vyberte adresář s tématy + + + + Choose LADSPA plugin directory + Vyberte adresář pro LADSPA pluginy + + + + Choose STK rawwave directory + Vyberte adresář pro STK rawwave + + + + Choose default SoundFont + Vyberte výchozí SoundFont + + + + Choose background artwork + Vyberte obrázek na pozadí + + + minutes minut + minute minuta - Display volume as dBFS - Zobrazit hlasitost v dBFS - - - Enable auto-save - Povolit automatické ukládání - - - Allow auto-save while playing - Povolit automatické ukládání během přehrávání - - + Disabled Vypnuto + Auto-save interval: %1 Interval automatického ukládání: %1 + Set the time between automatic backup to %1. Remember to also save your project manually. You can choose to disable saving while playing, something some older systems find difficult. Nastavte čas mezi automatickým zálohováním na %1. Nezapomeňte také svůj projekt uložit ručně. Můžete si vybrat, zda nechcete během přehrávání zakázat ukládání, což je problematické pro některé starší systémy. + + + Here you can select your preferred audio-interface. Depending on the configuration of your system during compilation time you can choose between ALSA, JACK, OSS and more. Below you see a box which offers controls to setup the selected audio-interface. + Zde vyberte preferované audio rozhraní. V závislosti na konfiguraci Vašeho systému při kompilaci můžete volit mezi ALSA, JACK, OSS a dalšími. Níže vidíte políčko, které nabízí možnost nastavení vybraného audio rozhraní. + + + + Here you can select your preferred MIDI-interface. Depending on the configuration of your system during compilation time you can choose between ALSA, OSS and more. Below you see a box which offers controls to setup the selected MIDI-interface. + Zde vyberte preferované MIDI rozhraní. V závislosti na konfiguraci Vašeho systému při kompilaci můžete volit mezi ALSA OSS a dalšími. Níže vidíte políčko, které nabízí možnost nastavení vybraného MIDI rozhraní. + Song + Tempo Tempo + Master volume Hlavní hlasitost + Master pitch - Hlavní ladění - - - Project saved - Projekt uložen - - - The project %1 is now saved. - Projekt %1 je nyní uložen. - - - Project NOT saved. - Projekt NENÍ uložen. - - - The project %1 was not saved! - Projekt %1 nebyl uložen! - - - Import file - Importovat soubor - - - MIDI sequences - MIDI sekvence - - - Hydrogen projects - Projekty Hydrogen - - - All file types - Všechny typy souborů - - - Empty project - Prázdný projekt - - - This project is empty so exporting makes no sense. Please put some items into Song Editor first! - Tento projekt je prázdný, jeho exportování nemá smysl. Nejdříve prosím vložte nějaké položky do Editoru skladby! - - - Select directory for writing exported tracks... - Vyberte adresář pro zápis exportovaných stop... - - - untitled - nepojmenovaný - - - Select file for project-export... - Vyberte soubor pro export projektu... - - - The following errors occured while loading: - Během načítání se vyskytly tyto chyby: - - - MIDI File (*.mid) - MIDI soubor (*.mid) + Transpozice + LMMS Error report Chybové hlášení LMMS + + Project saved + Projekt uložen + + + + The project %1 is now saved. + Projekt %1 je nyní uložen. + + + + Project NOT saved. + Projekt NENÍ uložen. + + + + The project %1 was not saved! + Projekt %1 nebyl uložen! + + + + Import file + Importovat soubor + + + + MIDI sequences + MIDI sekvence + + + + Hydrogen projects + Projekty Hydrogen + + + + All file types + Všechny typy souborů + + + + + Empty project + Prázdný projekt + + + + + This project is empty so exporting makes no sense. Please put some items into Song Editor first! + Tento projekt je prázdný, jeho exportování nemá smysl. Nejdříve prosím vložte nějaké položky do Editoru skladby! + + + + Select directory for writing exported tracks... + Vyberte adresář pro zápis exportovaných stop... + + + + + untitled + nepojmenovaný + + + + + Select file for project-export... + Vyberte soubor pro export projektu... + + + Save project Uložit projekt + + + MIDI File (*.mid) + MIDI soubor (*.mid) + + + + The following errors occured while loading: + Během načítání se vyskytly tyto chyby: + SongEditor + Could not open file Nemohu otevřít soubor - Could not write file - Nemohu zapsat soubor - - + Could not open file %1. You probably have no permissions to read this file. Please make sure to have at least read permissions to the file and try again. Nelze otevřít soubor %1. Pravděpodobně nemáte oprávnění číst tento soubor. Ujistěte se prosím, že máte oprávnění alespoň číst tento soubor a zkuste to znovu. - Error in file - Chyba v souboru - - - The file %1 seems to contain errors and therefore can't be loaded. - Soubor %1 pravděpodobně obsahuje chyby, a proto nemohl být načten. - - - Tempo - Tempo - - - TEMPO/BPM - TEMPO/BPM - - - tempo of song - tempo skladby - - - The tempo of a song is specified in beats per minute (BPM). If you want to change the tempo of your song, change this value. Every measure has four beats, so the tempo in BPM specifies, how many measures / 4 should be played within a minute (or how many measures should be played within four minutes). - Tempo skladby je uvedeno v úderech za minutu (BPM). Chcete-li změnit tempo skladby, změňte tuto hodnotu. Každý takt má čtyři doby (beats), takže tempo v BPM specifikuje kolik taktů / 4 bude za minutu přehráno (nebo kolik taktů bude přehráno ve čtyřech minutách). - - - High quality mode - Režim vysoké kvality - - - Master volume - Hlavní hlasitost - - - master volume - hlavní hlasitost - - - Master pitch - Hlavní ladění - - - master pitch - hlavní ladění - - - Value: %1% - Hodnota: %1% - - - Value: %1 semitones - Hodnota: %1 půltónů + + Could not write file + Nemohu zapsat soubor + Could not open %1 for writing. You probably are not permitted to write to this file. Please make sure you have write-access to the file and try again. Nelze zapisovat do souboru %1. Pravděpodobně nemáte oprávnění zapisovat do tohoto souboru. Ujistěte se prosím, že máte oprávnění zapisovat do tohoto souboru a zkuse to znovu. - template - šablona + + Error in file + Chyba v souboru - project - projekt + + The file %1 seems to contain errors and therefore can't be loaded. + Soubor %1 pravděpodobně obsahuje chyby, a proto nemohl být načten. + Version difference Rozdíl verzí + This %1 was created with LMMS %2. %1 byl vytvořen v LMMS %2. + + + template + šablona + + + + project + projekt + + + + Tempo + Tempo + + + + TEMPO/BPM + TEMPO/BPM + + + + tempo of song + tempo skladby + + + + The tempo of a song is specified in beats per minute (BPM). If you want to change the tempo of your song, change this value. Every measure has four beats, so the tempo in BPM specifies, how many measures / 4 should be played within a minute (or how many measures should be played within four minutes). + Tempo skladby je uvedeno v úderech za minutu (BPM). Chcete-li změnit tempo skladby, změňte tuto hodnotu. Každý takt má čtyři doby (beats), takže tempo v BPM specifikuje kolik taktů / 4 bude za minutu přehráno (nebo kolik taktů bude přehráno ve čtyřech minutách). + + + + High quality mode + Režim vysoké kvality + + + + + Master volume + Hlavní hlasitost + + + + master volume + hlavní hlasitost + + + + + Master pitch + Transpozice + + + + master pitch + transpozice + + + + Value: %1% + Hodnota: %1% + + + + Value: %1 semitones + Hodnota: %1 půltónů + SongEditorWindow + Song-Editor Editor skladby + Play song (Space) Přehrát skladbu (mezerník) + Record samples from Audio-device Nahrát samply z audio zařízení + Record samples from Audio-device while playing song or BB track - Nahrát samply z audio zařízení při přehrávání skladby stopy bicích/basů + Nahrát samply z audio zařízení při přehrávání skladby nebo stopy bicích/basů + Stop song (Space) Zastavit přehrávání (mezerník) - Add beat/bassline - Přidat bicí/basy - - - Add sample-track - Přidat stopu samplů - - - Add automation-track - Přidat stopu automatizace - - - Draw mode - Režim kreslení - - - Edit mode (select and move) - Režim úprav (označit a přesunout) - - + Click here, if you want to play your whole song. Playing will be started at the song-position-marker (green). You can also move it while playing. Klepněte sem, pokud chcete přehrát celou skladbu. Přehrávání začne v místě kde se nalézá zelený označovač pozice, se kterým lze též při přehrávání pohybovat. + Click here, if you want to stop playing of your song. The song-position-marker will be set to the start of your song. Klepněte sem, pokud chcete zastavit přehrávání skladby. Označovač pozice bude nastaven na začátek skladby. + Track actions Akce stopy + + Add beat/bassline + Přidat bicí/basy + + + + Add sample-track + Přidat stopu samplů + + + + Add automation-track + Přidat stopu automatizace + + + Edit actions Akce úprav + + Draw mode + Režim kreslení + + + + Edit mode (select and move) + Režim úprav (označit a přesunout) + + + Timeline controls Ovládání časové osy + Zoom controls Ovládání zvětšení @@ -6683,10 +8470,12 @@ Nezapomeňte také svůj projekt uložit ručně. Můžete si vybrat, zda nechce SpectrumAnalyzerControlDialog + Linear spectrum Lineární spektrum + Linear Y axis Lineární osa Y @@ -6694,14 +8483,17 @@ Nezapomeňte také svůj projekt uložit ručně. Můžete si vybrat, zda nechce SpectrumAnalyzerControls + Linear spectrum Lineární spektrum + Linear Y axis Lineární osa Y + Channel mode Režim kanálu @@ -6709,14 +8501,17 @@ Nezapomeňte také svůj projekt uložit ručně. Můžete si vybrat, zda nechce SubWindow + Close Zavřít + Maximize Maximalizovat + Restore Obnovit @@ -6724,6 +8519,8 @@ Nezapomeňte také svůj projekt uložit ručně. Můžete si vybrat, zda nechce TabWidget + + Settings for %1 Nastavení rpo %1 @@ -6731,74 +8528,93 @@ Nezapomeňte také svůj projekt uložit ručně. Můžete si vybrat, zda nechce TempoSyncKnob + + Tempo Sync Synchronizace tempa + No Sync Nesynchronizovat + Eight beats Osm dob + Whole note Celá nota + Half note Půlová nota + Quarter note Čtvrťová nota + 8th note Osminová nota + 16th note Šestnáctinová nota + 32nd note Dvaatřicetinová nota + Custom... Vlastní... + Custom Vlastní + Synced to Eight Beats Synchronizováno k osmi dobám + Synced to Whole Note Synchronizováno k celé notě + Synced to Half Note Synchronizováno k půlové notě + Synced to Quarter Note Synchronizováno ke čtvrťové notě + Synced to 8th Note Synchronizováno k osminové notě + Synced to 16th Note Synchronizováno k šestnáctinové notě + Synced to 32nd Note Synchronizováno k dvaatřicetinové notě @@ -6806,30 +8622,37 @@ Nezapomeňte také svůj projekt uložit ručně. Můžete si vybrat, zda nechce TimeDisplayWidget + click to change time units klepněte pro změnu časových jednotek + MIN MIN + SEC S + MSEC MS + BAR TAKT + BEAT DOBA + TICK TIK @@ -6837,34 +8660,43 @@ Nezapomeňte také svůj projekt uložit ručně. Můžete si vybrat, zda nechce TimeLineWidget + Enable/disable auto-scrolling Povolit/Zakázat automatický posun + Enable/disable loop-points Povolit/Zakázat body přehrávání ve smyčce + After stopping go back to begin Po skončení přetočit zpět na začátek + After stopping go back to position at which playing was started Po skončení přetočit zpět na pozici, ze které přehrávání začalo + After stopping keep position Po skončení zachovat pozici + + Hint Rada + Press <%1> to disable magnetic loop points. Stiskněte <%1> pro vypnutí magnetických bodů smyčky. + Hold <Shift> to move the begin loop point; Press <%1> to disable magnetic loop points. Držte <Shift> pro přesouvání počátečního bodu smyčky; stiskněte <%1> pro vypnutí magnetických bodů smyčky. @@ -6872,10 +8704,12 @@ Nezapomeňte také svůj projekt uložit ručně. Můžete si vybrat, zda nechce Track + Mute Ztlumit + Solo Sólo @@ -6883,49 +8717,71 @@ Nezapomeňte také svůj projekt uložit ručně. Můžete si vybrat, zda nechce TrackContainer + Couldn't import file Nemohu importovat soubor + Couldn't find a filter for importing file %1. You should convert this file into a format supported by LMMS using another software. Nemohu najít filtr pro import souboru %1. Měli byste tento soubor převést do formátu podporovaného LMMS pomocí jiného software. + Couldn't open file Nemohu otevřít soubor + Couldn't open file %1 for reading. Please make sure you have read-permission to the file and the directory containing the file and try again! Nemohu otevřít soubor %1 pro čtení. Přesvědčte se prosím, že máte právo ke čtení tohoto souboru a příslušného adresáře a zkuste to znovu! + Loading project... Načítám projekt... + + Cancel Zrušit + + Please wait... Prosím čekejte... - Importing MIDI-file... - Importuji MIDI soubor... + + Loading cancelled + Načítání zrušeno + + Project loading was cancelled. + Načítání projektu bylo zrušeno. + + + Loading Track %1 (%2/Total %3) Načítám Stopu %1 (%2/celkem %3) + + + Importing MIDI-file... + Importuji MIDI soubor... + TrackContentObject + Mute Ztlumit @@ -6933,46 +8789,59 @@ Přesvědčte se prosím, že máte právo ke čtení tohoto souboru a příslu TrackContentObjectView + Current position Aktuální pozice + + Hint Rada + Press <%1> and drag to make a copy. K vytvoření kopie stiskněte <%1> a táhněte myší. + Current length Aktuální délka + Press <%1> for free resizing. Stiskněte <%1> pro volnou změnu velikosti. + + %1:%2 (%3:%4 to %5:%6) %1:%2 (%3:%4 do %5:%6) + Delete (middle mousebutton) Smazat (prostřední tlačítko myši) + Cut Vyjmout + Copy Kopírovat + Paste Vložit + Mute/unmute (<%1> + middle click) Ztlumit/Odtlumit (<%1> + prostřední tlačítko myši) @@ -6980,193 +8849,243 @@ Přesvědčte se prosím, že máte právo ke čtení tohoto souboru a příslu TrackOperationsWidget + Press <%1> while clicking on move-grip to begin a new drag'n'drop-action. Při klepnutí na úchop držte <%1> pro zkopírování přetahované stopy. + Actions for this track Akce pro tuto stopu + Mute Ztlumit + + Solo Sólo + Mute this track Ztlumit tuto stopu + Clone this track Klonovat tuto stopu + Remove this track Odstranit tuto stopu + Clear this track - Klonovat tuto stopu + Smazat tuto stopu + FX %1: %2 Efekt %1: %2 + + Assign to new FX Channel + Přiřadit k novému efektovému kanálu + + + Turn all recording on Spustit všechna nahrávání + Turn all recording off Zastavit všechna nahrávání - - Assign to new FX Channel - Přiřadit k novému efektovému kanálu - TripleOscillatorView + Use phase modulation for modulating oscillator 1 with oscillator 2 Použít fázovou modulaci pro modulování oscilátoru 1 oscilátorem 2 + Use amplitude modulation for modulating oscillator 1 with oscillator 2 Použít amplitudovou modulaci pro modulování oscilátoru 1 oscilátorem 2 + Mix output of oscillator 1 & 2 Smíchat výstupy oscilátorů 1 a 2 + Synchronize oscillator 1 with oscillator 2 Synchronizovat oscilátor 1 oscilátorem 2 + Use frequency modulation for modulating oscillator 1 with oscillator 2 Použít frekvenční modulaci pro modulování oscilátoru 1 oscilátorem 2 + Use phase modulation for modulating oscillator 2 with oscillator 3 Použít fázovou modulaci pro modulování oscilátoru 2 oscilátorem 3 + Use amplitude modulation for modulating oscillator 2 with oscillator 3 Použít amplitudovou modulaci pro modulování oscilátoru 2 oscilátorem 3 + Mix output of oscillator 2 & 3 Smíchat výstupy oscilátorů 2 a 3 + Synchronize oscillator 2 with oscillator 3 Synchronizovat oscilátor 2 oscilátorem 3 + Use frequency modulation for modulating oscillator 2 with oscillator 3 Použít frekvenční modulaci pro modulování oscilátoru 2 oscilátorem 3 + Osc %1 volume: Osc %1 hlasitost: + With this knob you can set the volume of oscillator %1. When setting a value of 0 the oscillator is turned off. Otherwise you can hear the oscillator as loud as you set it here. Tímto otočným ovladačem můžete nastavit hlasitost oscilátoru %1. Když nastavíte hodnotu 0, oscilátor bude vypnutý. Jinak uslyšíte oscilátor tak hlasitě, jak si ho zde nastavíte. + Osc %1 panning: Osc %1 panoráma: + With this knob you can set the panning of the oscillator %1. A value of -100 means 100% left and a value of 100 moves oscillator-output right. Tímto otočným ovladačem můžete nastavit panoráma oscilátoru %1. Hodnota -100 znamená maximálně doleva, zatímco hodnota 100 přesouvá výstup oscilátoru doprava. + Osc %1 coarse detuning: Osc %1 hrubé rozladění: + semitones půltónů + With this knob you can set the coarse detuning of oscillator %1. You can detune the oscillator 24 semitones (2 octaves) up and down. This is useful for creating sounds with a chord. Tímto otočným ovladačem můžete provést hrubé rozladění oscilátoru %1. Můžete oscilátor rozladit o 24 půltónů (2 oktávy) nahoru nebo dolů. To je dobré pro vytvoření zvuku v akordu. + Osc %1 fine detuning left: Osc %1 jemné rozladění vlevo: + + cents centů + With this knob you can set the fine detuning of oscillator %1 for the left channel. The fine-detuning is ranged between -100 cents and +100 cents. This is useful for creating "fat" sounds. Tímto otočným ovladačem můžete provést jemné rozladění oscilátoru %1 v levém kanálu. Rozsah jemného rozladění je mezi -100 a +100 centy. To je dobré pro vytvoření "tlustého" zvuku. + Osc %1 fine detuning right: Osc %1 jemné rozladění vpravo: + With this knob you can set the fine detuning of oscillator %1 for the right channel. The fine-detuning is ranged between -100 cents and +100 cents. This is useful for creating "fat" sounds. Tímto otočným ovladačem můžete provést jemné rozladění oscilátoru %1 v pravém kanálu. Rozsah jemného rozladění je mezi -100 a +100 centy. To je dobré pro vytvoření "tlustého" zvuku. + Osc %1 phase-offset: Osc %1 posun fáze: + + degrees stupňů + With this knob you can set the phase-offset of oscillator %1. That means you can move the point within an oscillation where the oscillator begins to oscillate. For example if you have a sine-wave and have a phase-offset of 180 degrees the wave will first go down. It's the same with a square-wave. Tímto otočným ovladačem můžete nastavit fázový posun oscilátoru %1. To znamená, že můžete posunout bod, ve kterém oscilátor začne kmitat. Například pokud máte sinusovou vlnu s fázovým posunem 180 stupňů, vlna půjde nejdříve dolů. Totéž se stane u vlny pravoúhlé. + Osc %1 stereo phase-detuning: Osc %1 rozladění stereo fáze: + With this knob you can set the stereo phase-detuning of oscillator %1. The stereo phase-detuning specifies the size of the difference between the phase-offset of left and right channel. This is very good for creating wide stereo sounds. Tímto otočným ovladačem můžete nastavit rozladění fáze oscilátoru %1. Rozladění stereo fáze určuje velikost rozdílu mezi fázovým posunem levého a pravého kanálu. To je velmi dobré pro vytvoření širokého stereo zvuku. + Use a sine-wave for current oscillator. Použít sinusovou vlnu pro aktuální oscilátor. + Use a triangle-wave for current oscillator. Použít trojúhelníkovou vlnu pro aktuální oscilátor. + Use a saw-wave for current oscillator. Použít pilovitou vlnu pro aktuální oscilátor. + Use a square-wave for current oscillator. Použít pravoúhlou vlnu pro aktuální oscilátor. + Use a moog-like saw-wave for current oscillator. Použít pilovitou vlnu typu Moog pro tento oscilátor. + Use an exponential wave for current oscillator. Použít exponenciální vlnu pro aktuální oscilátor. + Use white-noise for current oscillator. Použít bílý šum pro aktuální oscilátor. + Use a user-defined waveform for current oscillator. Použít vlastní vlnu pro aktuální oscilátor. @@ -7174,14 +9093,17 @@ Přesvědčte se prosím, že máte právo ke čtení tohoto souboru a příslu VersionedSaveDialog + Increment version number Zvýšit číslo verze + Decrement version number Snížení čísla verze + already exists. Do you want to replace it? již existuje. Přejete si jej přepsat? @@ -7189,90 +9111,113 @@ Přesvědčte se prosím, že máte právo ke čtení tohoto souboru a příslu VestigeInstrumentView + Open other VST-plugin Otevřít jiný VST plugin + Click here, if you want to open another VST-plugin. After clicking on this button, a file-open-dialog appears and you can select your file. Klepněte sem, pokud chcete otevřít jiný VST plugin. Po klepnutí na toto tlačítko se objeví okno, ve kterém můžete soubor vybrat. - Show/hide GUI - Zobrazit/Skrýt grafické rozhraní - - - Click here to show or hide the graphical user interface (GUI) of your VST-plugin. - Klepněte sem pro zobrazení nebo skrytí grafického rozhraní (GUI) pro vaše VST pluginy. - - - Turn off all notes - Vypnout všechny noty - - - Open VST-plugin - Otevřít jiný VST plugin - - - DLL-files (*.dll) - DLL soubory (*.dll) - - - EXE-files (*.exe) - EXE soubory (*.exe) - - - No VST-plugin loaded - VST plugin není nahrán - - + Control VST-plugin from LMMS host Ovládání VST pluginu hostitelským programem LMMS + Click here, if you want to control VST-plugin from host. Klepněte sem, pokud chcete ovládat VST plugin hostitelským programem. + Open VST-plugin preset Otevřít předvolbu VST pluginu + Click here, if you want to open another *.fxp, *.fxb VST-plugin preset. Klepněte sem, chcete-li otevřít jinou *.fxp, *.fxb předvolbu VST pluginu. + Previous (-) Předchozí (-) + + Click here, if you want to switch to another VST-plugin preset program. Klepněte sem, chcete-li přepnout na jiný přednastavený VST program. + Save preset Uložit předvolbu + Click here, if you want to save current VST-plugin preset program. Klepněte sem, chcete-li uložit aktuální předvolbu programu VST pluginu. + Next (+) Další (+) + Click here to select presets that are currently loaded in VST. Klepněte sem, chcete-li vybrat předvolby, které jsou aktuálně nahrány ve VST. + + Show/hide GUI + Zobrazit/Skrýt grafické rozhraní + + + + Click here to show or hide the graphical user interface (GUI) of your VST-plugin. + Klepněte sem pro zobrazení nebo skrytí grafického rozhraní (GUI) pro vaše VST pluginy. + + + + Turn off all notes + Vypnout všechny noty + + + + Open VST-plugin + Otevřít jiný VST plugin + + + + DLL-files (*.dll) + DLL soubory (*.dll) + + + + EXE-files (*.exe) + EXE soubory (*.exe) + + + + No VST-plugin loaded + VST plugin není nahrán + + + Preset Předvolba + by od + - VST plugin control – ovládání VST pluginu @@ -7280,10 +9225,12 @@ Přesvědčte se prosím, že máte právo ke čtení tohoto souboru a příslu VisualizationWidget + click to enable/disable visualization of master-output klepněte pro zapnutí/vypnutí vizualizace hlavního výstupu + Click to enable Klepněte pro zapnutí @@ -7291,54 +9238,69 @@ Přesvědčte se prosím, že máte právo ke čtení tohoto souboru a příslu VstEffectControlDialog + Show/hide Ukázat/Skrýt + Control VST-plugin from LMMS host Ovládání VST pluginu hostitelským programem LMMS + Click here, if you want to control VST-plugin from host. Klepněte sem, pokud chcete ovládat VST plugin hostitelským programem. + Open VST-plugin preset Otevřít předvolbu VST pluginu + Click here, if you want to open another *.fxp, *.fxb VST-plugin preset. Klepněte sem, chcete-li otevřít jinou *.fxp, *.fxb předvolbu VST pluginu. + Previous (-) Předchozí (-) + + Click here, if you want to switch to another VST-plugin preset program. Klepněte sem, chcete-li přepnout na jiný přednastavený VST program. + Next (+) Další (+) + Click here to select presets that are currently loaded in VST. - Klepněte sem, chcete-li vybrat předvolbu, která je aktuálně nahraná ve VST. + Klepněte sem, chcete-li vybrat předvolby, které jsou aktuálně nahrány ve VST. + Save preset Uložit předvolbu + Click here, if you want to save current VST-plugin preset program. Klepněte sem, chcete-li uložit aktuální předvolbu programu VST pluginu. + + Effect by: Efekt od: + &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /> @@ -7346,173 +9308,217 @@ Přesvědčte se prosím, že máte právo ke čtení tohoto souboru a příslu VstPlugin - Loading plugin - Načítám plugin + + + The VST plugin %1 could not be loaded. + VST plugin %1 nelze načíst. + Open Preset Otevřít předvolbu + + Vst Plugin Preset (*.fxp *.fxb) Předvolba VST pluginu (*.fxp *.fxb) + : default : výchozí + " " + ' ' + Save Preset Uložit předvolbu + .fxp .fxp + .FXP .FXP + .FXB .FXB + .fxb .fxb - Please wait while loading VST plugin... - Počkejte prosím, než se načte VST plugin... + + Loading plugin + Načítám plugin - The VST plugin %1 could not be loaded. - VST plugin %1 nelze načíst. + + Please wait while loading VST plugin... + Počkejte prosím, než se načte VST plugin... WatsynInstrument + Volume A1 Hlasitost A1 + Volume A2 Hlasitost A2 + Volume B1 Hlasitost B1 + Volume B2 Hlasitost B2 + Panning A1 Panoráma A1 + Panning A2 Panoráma A2 + Panning B1 Panoráma B1 + Panning B2 Panoráma B2 + Freq. multiplier A1 Násobič frekv. A1 + Freq. multiplier A2 Násobič frekv. A2 + Freq. multiplier B1 Násobič frekv. B1 + Freq. multiplier B2 Násobič frekv. B2 + Left detune A1 Rozladění vlevo A1 + Left detune A2 Rozladění vlevo A2 + Left detune B1 Rozladění vlevo B1 + Left detune B2 Rozladění vlevo B2 + Right detune A1 Rozladění vpravo A1 + Right detune A2 Rozladění vpravo A2 + Right detune B1 Rozladění vpravo B1 + Right detune B2 Rozladění vpravo B2 + A-B Mix Směšovač A-B + A-B Mix envelope amount Množství obálky směšovače A-B + A-B Mix envelope attack Náběh obálky směšovače A-B + A-B Mix envelope hold - Množství držení směšovače A-B + Množství zadržení směšovače A-B + A-B Mix envelope decay - Útlum obálky směšovače A-B + Pokles obálky směšovače A-B + A1-B2 Crosstalk Přeslech A1-B2 + A2-A1 modulation Modulace A1-B2 + B2-B1 modulation Modulace B2-B1 + Selected graph Zvolený graf @@ -7520,213 +9526,291 @@ Přesvědčte se prosím, že máte právo ke čtení tohoto souboru a příslu WatsynView - Select oscillator A1 - Vybrat oscilátor A1 - - - Select oscillator A2 - Vybrat oscilátor A2 - - - Select oscillator B1 - Vybrat oscilátor B1 - - - Select oscillator B2 - Vybrat oscilátor B2 - - - Mix output of A2 to A1 - Přimíchat výstup A1 do A2 - - - Modulate amplitude of A1 with output of A2 - Modulovat amplitudu A1 výstupem A2 - - - Ring-modulate A1 and A2 - Kruhově modulovat A1 a A2 - - - Modulate phase of A1 with output of A2 - Modulovat fázi A1 výstupem A2 - - - Mix output of B2 to B1 - Přimíchat výstup B1 do B2 - - - Modulate amplitude of B1 with output of B2 - Modulovat amplitudu B1 výstupem B2 - - - Ring-modulate B1 and B2 - Kruhově modulovat B1 a B2 - - - Modulate phase of B1 with output of B2 - Modulovat fázi B1 výstupem B2 - - - Draw your own waveform here by dragging your mouse on this graph. - Kreslení vlastní křivky tahem myši na tomto grafu. - - - Load waveform - Načíst vlnu - - - Click to load a waveform from a sample file - Klepněte pro načtení vlny ze souboru samplů - - - Phase left - Fáze vlevo - - - Click to shift phase by -15 degrees - Klepněte pro posun fáze o -15 stupňů - - - Phase right - Fáze vpravo - - - Click to shift phase by +15 degrees - Klepněte pro posun fáze o +15 stupňů - - - Normalize - Normalizovat - - - Click to normalize - Klepněte pro normalizaci - - - Invert - Převrátit - - - Click to invert - Klepněte pro převrácení - - - Smooth - Uhladit - - - Click to smooth - Klepněte pro vyhlazení - - - Sine wave - Sinusová vlna - - - Click for sine wave - Klepněte pro sinusovou vlnu - - - Triangle wave - Trojúhelníková vlna - - - Click for triangle wave - Klepněte pro trojúhelníkovou vlnu - - - Click for saw wave - Klepněte pro pilovitou vlnu - - - Square wave - Pravoúhlá vlna - - - Click for square wave - Klepněte pro pravoúhlou vlnu - - + + + + Volume Hlasitost + + + + Panning Panoráma + + + + Freq. multiplier Násobič frekv. + + + + Left detune Rozladění vlevo + + + + + + + + cents centů + + + + Right detune Rozladění vpravo + A-B Mix Směšovač A-B + Mix envelope amount Množství obálky směšovače + Mix envelope attack Náběh obálky směšovače + Mix envelope hold - Držení obálky směšovače + Zadržení obálky směšovače + Mix envelope decay - Útlum obálky směšovače + Pokles obálky směšovače + Crosstalk Přeslech + + + Select oscillator A1 + Vybrat oscilátor A1 + + + + Select oscillator A2 + Vybrat oscilátor A2 + + + + Select oscillator B1 + Vybrat oscilátor B1 + + + + Select oscillator B2 + Vybrat oscilátor B2 + + + + Mix output of A2 to A1 + Přimíchat výstup A1 do A2 + + + + Modulate amplitude of A1 with output of A2 + Modulovat amplitudu A1 výstupem A2 + + + + Ring-modulate A1 and A2 + Kruhově modulovat A1 a A2 + + + + Modulate phase of A1 with output of A2 + Modulovat fázi A1 výstupem A2 + + + + Mix output of B2 to B1 + Přimíchat výstup B1 do B2 + + + + Modulate amplitude of B1 with output of B2 + Modulovat amplitudu B1 výstupem B2 + + + + Ring-modulate B1 and B2 + Kruhově modulovat B1 a B2 + + + + Modulate phase of B1 with output of B2 + Modulovat fázi B1 výstupem B2 + + + + + + + Draw your own waveform here by dragging your mouse on this graph. + Kreslení vlastní křivky tahem myši na tomto grafu. + + + + Load waveform + Načíst vlnu + + + + Click to load a waveform from a sample file + Klepněte pro načtení vlny ze souboru samplů + + + + Phase left + Fáze vlevo + + + + Click to shift phase by -15 degrees + Klepněte pro posun fáze o -15 stupňů + + + + Phase right + Fáze vpravo + + + + Click to shift phase by +15 degrees + Klepněte pro posun fáze o +15 stupňů + + + + Normalize + Normalizovat + + + + Click to normalize + Klepněte pro normalizaci + + + + Invert + Převrátit + + + + Click to invert + Klepněte pro převrácení + + + + Smooth + Uhladit + + + + Click to smooth + Klepněte pro vyhlazení + + + + Sine wave + Sinusová vlna + + + + Click for sine wave + Klepněte pro sinusovou vlnu + + + + + Triangle wave + Trojúhelníková vlna + + + + Click for triangle wave + Klepněte pro trojúhelníkovou vlnu + + + + Click for saw wave + Klepněte pro pilovitou vlnu + + + + Square wave + Pravoúhlá vlna + + + + Click for square wave + Klepněte pro pravoúhlou vlnu + ZynAddSubFxInstrument + Portamento Portamento + Filter Frequency Frekvence filtru + Filter Resonance Rezonance filtru + Bandwidth Šířka pásma + FM Gain Zesílení FM + Resonance Center Frequency Střední frekvence rezonance + Resonance Bandwidth Šířka pásma rezonance + Forward MIDI Control Change Events Odesílat události MIDI Control Change @@ -7734,121 +9818,150 @@ Přesvědčte se prosím, že máte právo ke čtení tohoto souboru a příslu ZynAddSubFxView - Show GUI - Ukázar grafické rozhraní - - - Click here to show or hide the graphical user interface (GUI) of ZynAddSubFX. - Klepněte sem pro zobrazení nebo skrytí grafického uživatelského rozhraní (GUI) ZynAddSubFX. - - + Portamento: Portamento: + PORT PORT + Filter Frequency: Frekvence filtru: + FREQ FREKV + Filter Resonance: Rezonance filtru: + RES REZ + Bandwidth: Šířka pásma: + BW ŠP + FM Gain: Zesílení FM: + FM GAIN ZISK FM + Resonance center frequency: Střední frekvence rezonance: + RES CF SF REZ + Resonance bandwidth: Šířka pásma rezonance: + RES BW ŠP REZ + Forward MIDI Control Changes Odesílat MIDI Control Change + + + Show GUI + Ukázar grafické rozhraní + + + + Click here to show or hide the graphical user interface (GUI) of ZynAddSubFX. + Klepněte sem pro zobrazení nebo skrytí grafického uživatelského rozhraní (GUI) ZynAddSubFX. + audioFileProcessor + Amplify Zesílení + Start of sample Začátek samplu + End of sample Konec samplu - Reverse sample - Přehrávat pozpátku - - - Stutter - Pokračování v přehrávání samplu při změně noty - - + Loopback point Začátek smyčky + + Reverse sample + Přehrávat pozpátku + + + Loop mode Režim smyčky + + Stutter + Pokračování v přehrávání samplu při změně noty + + + Interpolation mode Režim interpolace + None Žádný + Linear Lineární + Sinc Sinusový + Sample not found: %1 Vzorek nenalezen: %1 @@ -7856,6 +9969,7 @@ Přesvědčte se prosím, že máte právo ke čtení tohoto souboru a příslu bitInvader + Samplelength Délka samplu @@ -7863,165 +9977,205 @@ Přesvědčte se prosím, že máte právo ke čtení tohoto souboru a příslu bitInvaderView + Sample Length Délka samplu - Sine wave - Sinusová vlna - - - Triangle wave - Trojúhelníková vlna - - - Saw wave - Pilovitá vlna - - - Square wave - Pravoúhlá vlna - - - White noise wave - Bílý šum - - - User defined wave - Vlna definovaná uživatelem - - - Smooth - Uhladit - - - Click here to smooth waveform. - Klepněte sem pro vyhlazení vlny. - - - Interpolation - Interpolovat - - - Normalize - Normalizovat - - + Draw your own waveform here by dragging your mouse on this graph. Kreslení vlastní křivky tahem myši na tomto grafu. + + Sine wave + Sinusová vlna + + + Click for a sine-wave. Klepněte sem pro sinusovou vlnu. + + Triangle wave + Trojúhelníková vlna + + + Click here for a triangle-wave. Klepněte sem pro trojúhelníkovou vlnu. + + Saw wave + Pilovitá vlna + + + Click here for a saw-wave. Klepněte sem pro pilovitou vlnu. + + Square wave + Pravoúhlá vlna + + + Click here for a square-wave. Klepněte sem pro pravoúhlou vlnu. + + White noise wave + Bílý šum + + + Click here for white-noise. Klepněte sem pro bílý šum. + + User defined wave + Vlna definovaná uživatelem + + + Click here for a user-defined shape. Klepněte sem pro uživatelem definovaný tvar. + + + Smooth + Vyhladit + + + + Click here to smooth waveform. + Klepněte sem pro vyhlazení vlny. + + + + Interpolation + Interpolovat + + + + Normalize + Normalizovat + dynProcControlDialog + INPUT VSTUP + Input gain: Zesílení vstupu: + OUTPUT VÝSTUP + Output gain: Zesílení výstupu: + ATTACK NÁBĚH + Peak attack time: Délka náběhu špičky: + RELEASE UVOLNĚNÍ + Peak release time: Délka uvolnění špičky: + Reset waveform Obnovení vlny + Click here to reset the wavegraph back to default - Klepněte sem pro obnovení křivky zpět do výchozího stavu + Klepněte sem pro obnovení zobrazení křivky zpět do výchozího stavu + Smooth waveform Vyhlazení vlny + Click here to apply smoothing to wavegraph Klepněte sem pro vyhlazení křivky + Increase wavegraph amplitude by 1dB Zvýšení amplitudy křivky o 1 dB + Click here to increase wavegraph amplitude by 1dB Klepněte sem pro zvýšení amplitudy křivky o 1 dB + Decrease wavegraph amplitude by 1dB Snížení amplitudy křivky o 1 dB + Click here to decrease wavegraph amplitude by 1dB Klepněte sem pro snížení amplitudy křivky o 1 dB + Stereomode Maximum Režim maximálního sterea + Process based on the maximum of both stereo channels Zpracování vycházející z maxima obou stereo kanálů + Stereomode Average Režim průměru sterea + Process based on the average of both stereo channels Zpracování vycházející z průměru obou stereo kanálů + Stereomode Unlinked Režim nepropojeného sterea + Process each stereo channel independently Zpracování každého stereo kanálu zvlášť @@ -8029,160 +10183,40 @@ Přesvědčte se prosím, že máte právo ke čtení tohoto souboru a příslu dynProcControls + Input gain Zesílení vstupu + Output gain Zesílení výstupu + Attack time Doba náběhu + Release time - Délka uvolnění + Délka doznění + Stereo mode Režim sterea - - expressiveView - - Select oscillator W1 - Vybrat oscilátor W1 - - - Select oscillator W2 - Vybrat oscilátor W2 - - - Select oscillator W3 - Vybrat oscilátor W3 - - - Select OUTPUT 1 - Vybrat VÝSTUP 1 - - - Select OUTPUT 2 - Vybrat VÝSTUP 2 - - - Open help window - Otevřít okno nápovědy - - - Sine wave - Sinusová vlna - - - Click for a sine-wave. - Klepněte sem pro sinusovou vlnu. - - - Moog-Saw wave - Pilovitá vlna typu Moog - - - Click for a Moog-Saw-wave. - Klepněte pro pilovitou vlnu typu Moog. - - - Exponential wave - Exponenciální vlna - - - Click for an exponential wave. - Klepněte pro exponenciální vlnu. - - - Saw wave - Pilovitá vlna - - - Click here for a saw-wave. - Klepněte sem pro pilovitou vlnu. - - - User defined wave - Vlna definovaná uživatelem - - - Click here for a user-defined shape. - Klepněte sem pro uživatelem definovaný tvar. - - - Triangle wave - Trojúhelníková vlna - - - Click here for a triangle-wave. - Klepněte sem pro trojúhelníkovou vlnu. - - - Square wave - Pravoúhlá vlna - - - Click here for a square-wave. - Klepněte sem pro pravoúhlou vlnu. - - - White noise wave - Bílý šum - - - Click here for white-noise. - Klepněte sem pro bílý šum. - - - WaveInterpolate - Interpolace vlnění - - - ExpressionValid - Platnost výrazu - - - General purpose 1: - Celkový účel 1: - - - General purpose 2: - Celkový účel 2: - - - General purpose 3: - Celkový účel 3: - - - O1 panning: - O1 vyvážení: - - - O2 panning: - O2 vyvážení: - - - Release transition: - Přechod mezi uvolněním: - - - Smoothness - Hladkost - - fxLineLcdSpinBox + Assign to: Přiřadit k: + New FX Channel Nový efektový kanál @@ -8190,6 +10224,7 @@ Přesvědčte se prosím, že máte právo ke čtení tohoto souboru a příslu graphModel + Graph Graf @@ -8197,50 +10232,62 @@ Přesvědčte se prosím, že máte právo ke čtení tohoto souboru a příslu kickerInstrument + Start frequency Počáteční frekvence + End frequency Konečná frekvence - Gain - Zisk - - + Length Délka + Distortion Start Začátek zkreslení + Distortion End Konec zkreslení + + Gain + Zisk + + + Envelope Slope Sklon frekvence + Noise Šum + Click Klik + Frequency Slope Sklon frekvence + Start from note Začít od noty + End to note Skončit na notě @@ -8248,42 +10295,52 @@ Přesvědčte se prosím, že máte právo ke čtení tohoto souboru a příslu kickerInstrumentView + Start frequency: Počáteční frekvence: + End frequency: Konečná frekvence: - Gain: - Zisk: - - + Frequency Slope: Sklon frekvence: + + Gain: + Zisk: + + + Envelope Length: Délka obálky: + Envelope Slope: Sklon obálky: + Click: Klik: + Noise: Šum: + Distortion Start: Začátek zkreslení: + Distortion End: Konec zkreslení: @@ -8291,26 +10348,37 @@ Přesvědčte se prosím, že máte právo ke čtení tohoto souboru a příslu ladspaBrowserView + + Available Effects Dostupné efekty + + Unavailable Effects Nedostupné efekty + + Instruments Nástroje + + Analysis Tools Analyzační nástroje + + Don't know Neznámé + This dialog displays information on all of the LADSPA plugins LMMS was able to locate. The plugins are divided into five categories based upon an interpretation of the port types and names. Available Effects are those that can be used by LMMS. In order for LMMS to be able to use an effect, it must, first and foremost, be an effect, which is to say, it has to have both input channels and output channels. LMMS identifies an input channel as an audio rate port containing 'in' in the name. Output channels are identified by the letters 'out'. Furthermore, the effect must have the same number of inputs and outputs and be real time capable. @@ -8340,6 +10408,7 @@ Neznámé jsou pluginy, pro které nebyly identifikovány žádné vstupní nebo Poklepáním na kterýkoliv modul se zobrazí informace o portech. + Type: Typ: @@ -8347,10 +10416,12 @@ Poklepáním na kterýkoliv modul se zobrazí informace o portech. ladspaDescription + Plugins Pluginy + Description Popis @@ -8358,66 +10429,83 @@ Poklepáním na kterýkoliv modul se zobrazí informace o portech. ladspaPortDialog + Ports Porty + Name Název + Rate Druh + Direction Směr + Type Typ + Min < Default < Max Min < Výchozí < Max + Logarithmic Logaritmický + SR Dependent SR závislý + Audio Zvuk + Control Ovládání + Input Vstup + Output Výstup + Toggled Zapnuto + Integer Celočíselný + Float S plovoucí čárkou + + Yes Ano @@ -8425,46 +10513,57 @@ Poklepáním na kterýkoliv modul se zobrazí informace o portech. lb302Synth + VCF Cutoff Frequency VCF frekvence vypnutí + VCF Resonance VCF rezonance + VCF Envelope Mod VCF modulace obálky + VCF Envelope Decay VCF útlum obálky + Distortion Zkreslení + Waveform Vlna + Slide Decay Útlum sklouznutí + Slide Sklouznutí + Accent Důraz + Dead Dead + 24dB/oct Filter Filtr 24dB/okt @@ -8472,122 +10571,153 @@ Poklepáním na kterýkoliv modul se zobrazí informace o portech. lb302SynthView + Cutoff Freq: Frekvence odstřihnutí: + Resonance: Rezonance: + Env Mod: Modulace obálky: + Decay: Útlum: + 303-es-que, 24dB/octave, 3 pole filter 3pólový filtr 303-es-que, 24dB/okt + Slide Decay: Útlum sklouznutí: + DIST: Zkreslení: + Saw wave Pilovitá vlna + Click here for a saw-wave. Klepněte sem pro pilovitou vlnu. + Triangle wave Trojúhelníková vlna + Click here for a triangle-wave. Klepněte sem pro trojúhelníkovou vlnu. + Square wave Pravoúhlá vlna + Click here for a square-wave. Klepněte sem pro pravoúhlou vlnu. + Rounded square wave Oblá pravoúhlá vlna + Click here for a square-wave with a rounded end. Klepněte sem pro pravoúhlou vlnu s oblým zakončením. + Moog wave Vlna typu Moog + Click here for a moog-like wave. Klepněte sem pro vlnu typu Moog. + Sine wave Sinusová vlna + Click for a sine-wave. Klepněte sem pro sinusovou vlnu. + + White noise wave Bílý šum + Click here for an exponential wave. Klepněte sem pro exponenciální vlnu. + Click here for white-noise. Klepněte sem pro bílý šum. + Bandlimited saw wave Pásmově omezená pilovitá vlna + Click here for bandlimited saw wave. Klepněte sem pro pásmově omezenou pilovitou vlnu. + Bandlimited square wave Pásmově zúžená pravoúhlá vlna + Click here for bandlimited square wave. Klepněte sem pro pásmově zúženou pravoúhlou vlnu. + Bandlimited triangle wave Pásmově zúžená trojúhelníková vlna + Click here for bandlimited triangle wave. Klepněte sem pro pásmově zúženou trojúhelníkovou vlnu. + Bandlimited moog saw wave Pásmově zúžená pilovitá vlna typu Moog + Click here for bandlimited moog saw wave. Klepněte sem pro úzkopásmovou pilovitou vlnu typu Moog. @@ -8595,118 +10725,147 @@ Poklepáním na kterýkoliv modul se zobrazí informace o portech. malletsInstrument + Hardness Tvrdost + Position Pozice + Vibrato Gain Zisk vibráta + Vibrato Freq Frekvence vibráta + Stick Mix Mix paliček + Modulator Modulátor + Crossfade Prolínání (crossfade) + LFO Speed LFO Rychlost + LFO Depth LFO Hloubka + ADSR ADSR + Pressure Tlak + Motion Pohyb + Speed Rychlost + Bowed Smyčcem + Spread Šíře + Marimba Marimba + Vibraphone Vibrafon + Agogo Agogo + Wood1 Dřevo1 + Reso Rezo + Wood2 Dřevo2 + Beats Údery + Two Fixed - Dvě pevné + Dvě spojené + Clump Svazek + Tubular Bells Trubicové zvony + Uniform Bar Obyčejná tyč + Tuned Bar Laděná tyč + Glass Sklo + Tibetan Bowl Tibetská zpívající mísa @@ -8714,149 +10873,186 @@ Poklepáním na kterýkoliv modul se zobrazí informace o portech. malletsInstrumentView + Instrument Nástroj + Spread Šíře + Spread: Šíře: - Hardness - Tvrdost - - - Hardness: - Tvrdost: - - - Position - Pozice - - - Position: - Pozice: - - - Vib Gain - Vib zisk - - - Vib Gain: - Vib zisk: - - - Vib Freq - Vib frekv - - - Vib Freq: - Vib frekv: - - - Stick Mix - Mix paliček - - - Stick Mix: - Mix paliček: - - - Modulator - Modulátor - - - Modulator: - Modulátor: - - - Crossfade - Prolínání (crossfade) - - - Crossfade: - Prolínání (crossfade): - - - LFO Speed - LFO Rychlost - - - LFO Speed: - LFO Rychlost: - - - LFO Depth - LFO Hloubka - - - LFO Depth: - LFO Hloubka: - - - ADSR - ADSR - - - ADSR: - ADSR: - - - Pressure - Tlak - - - Pressure: - Tlak: - - - Speed - Rychlost - - - Speed: - Rychlost: - - + Missing files Chybějící soubory + Your Stk-installation seems to be incomplete. Please make sure the full Stk-package is installed! Zdá se, že instalace Stk není kompletní. Ujistěte se prosím, že je nainstalován celý balík Stk! + + + Hardness + Tvrdost + + + + Hardness: + Tvrdost: + + + + Position + Pozice + + + + Position: + Pozice: + + + + Vib Gain + Vib zisk + + + + Vib Gain: + Vib zisk: + + + + Vib Freq + Vib frekv + + + + Vib Freq: + Vib frekv: + + + + Stick Mix + Mix paliček + + + + Stick Mix: + Mix paliček: + + + + Modulator + Modulátor + + + + Modulator: + Modulátor: + + + + Crossfade + Prolínání (crossfade) + + + + Crossfade: + Prolínání (crossfade): + + + + LFO Speed + LFO Rychlost + + + + LFO Speed: + LFO Rychlost: + + + + LFO Depth + LFO Hloubka + + + + LFO Depth: + LFO Hloubka: + + + + ADSR + ADSR + + + + ADSR: + ADSR: + + + + Pressure + Tlak + + + + Pressure: + Tlak: + + + + Speed + Rychlost + + + + Speed: + Rychlost: + manageVSTEffectView + - VST parameter control - řízení parametrů VST + VST Sync VST synch + Click here if you want to synchronize all parameters with VST plugin. Klepněte sem, chcete-li synchronizovat všechny parametry s VST pluginem. + + Automated Automaticky + Click here if you want to display automated parameters only. Klepněte sem, pokud chcete pouze zobrazit parametry automatizace. + Close Zavřít + Close VST effect knob-controller window. Zavřít okno otočných ovladačů VST efektu. @@ -8864,30 +11060,39 @@ Poklepáním na kterýkoliv modul se zobrazí informace o portech. manageVestigeInstrumentView + + - VST plugin control - ovládání VST pluginu + VST Sync VST synch + Click here if you want to synchronize all parameters with VST plugin. Klepněte sem, chcete-li synchronizovat všechny parametry s VST pluginem. + + Automated Automaticky + Click here if you want to display automated parameters only. Klepněte sem, pokud chcete pouze zobrazit parametry automatizace. + Close Zavřít + Close VST plugin knob-controller window. Zavřít okno otočných ovladačů VST pluginu. @@ -8895,118 +11100,147 @@ Poklepáním na kterýkoliv modul se zobrazí informace o portech. opl2instrument + Patch Patch + Op 1 Attack Op 1 náběh + Op 1 Decay Op 1 útlum + Op 1 Sustain Op 1 vydržení + Op 1 Release Op 1 uvolnění + Op 1 Level Op 1 úroveň + Op 1 Level Scaling Op 1 škálování úrovně + Op 1 Frequency Multiple Op 1 násobení frekvence + Op 1 Feedback Op 1 zpětná vazba + Op 1 Key Scaling Rate Op 1 rychlost podle výšky klávesy + Op 1 Percussive Envelope Op 1 perkusivní obálka + Op 1 Tremolo Op 1 tremolo + Op 1 Vibrato Op 1 vibrato + Op 1 Waveform Op 1 vlna + Op 2 Attack Op 2 náběh + Op 2 Decay Op 2 útlum + Op 2 Sustain Op 2 vydržení + Op 2 Release Op 2 uvolnění + Op 2 Level Op 2 úroveň + Op 2 Level Scaling Op 2 škálování úrovně + Op 2 Frequency Multiple Op 2 násobení frekvence + Op 2 Key Scaling Rate Op 2 rychlost podle výšky klávesy + Op 2 Percussive Envelope Op 2 perkusivní obálka + Op 2 Tremolo Op 2 tremolo + Op 2 Vibrato Op 2 vibrato + Op 2 Waveform Op 2 tvar vlny + FM FM + Vibrato Depth Hloubka vibráta + Tremolo Depth Hloubka tremola @@ -9014,18 +11248,26 @@ Poklepáním na kterýkoliv modul se zobrazí informace o portech. opl2instrumentView + + Attack Náběh + + Decay Útlum + + Release - Uvolnění + Doznění + + Frequency multiplier Násobič frekvence @@ -9033,10 +11275,12 @@ Poklepáním na kterýkoliv modul se zobrazí informace o portech. organicInstrument + Distortion Zkreslení + Volume Hlasitost @@ -9044,50 +11288,63 @@ Poklepáním na kterýkoliv modul se zobrazí informace o portech. organicInstrumentView + Distortion: Zkreslení: - Volume: - Hlasitost: - - - Randomise - Nastavit náhodně - - - Osc %1 waveform: - Osc %1 vlna: - - - Osc %1 volume: - Osc %1 hlasitost: - - - Osc %1 panning: - Osc %1 panoráma: - - - cents - centů - - + The distortion knob adds distortion to the output of the instrument. Otočný ovladač zkreslení přidá zkreslení k výstupu nástroje. + + Volume: + Hlasitost: + + + The volume knob controls the volume of the output of the instrument. It is cumulative with the instrument window's volume control. Otočný ovladač hlasitosti ovládá hlasitost výstupu nástroje. Sčítá se s ovládáním hlasitosti okna nástroje. + + Randomise + Nastavit náhodně + + + The randomize button randomizes all knobs except the harmonics,main volume and distortion knobs. Tlačítko Randomize náhodně nastaví všechny ovladače kromě ovladače harmonických, hlavní hlasitosti a zkreslení. + + + Osc %1 waveform: + Osc %1 vlna: + + + + Osc %1 volume: + Osc %1 hlasitost: + + + + Osc %1 panning: + Osc %1 panoráma: + + + Osc %1 stereo detuning Osc %1 rozladění sterea + + cents + centů + + + Osc %1 harmonic: Osc %1 harmonické: @@ -9095,265 +11352,351 @@ Poklepáním na kterýkoliv modul se zobrazí informace o portech. FreeBoyInstrument + Sweep time Trvání sweepu + Sweep direction Směr sweepu + Sweep RtShift amount Úroveň pro změnu frekvence sweepu + + Wave Pattern Duty Pracovní cyklus vlnového patternu + Channel 1 volume Hlasitost kanálu 1 + + + Volume sweep direction Směr hlasitosti sweepu + + + Length of each step in sweep Délka každého kroku ve sweepu + Channel 2 volume Hlasitost kanálu 2 + Channel 3 volume Hlasitost kanálu 3 + Channel 4 volume Hlasitost kanálu 4 + + Shift Register width + Posun šířky registru + + + Right Output level Úroveň pravého výstupu + Left Output level Úroveň levého výstupu + Channel 1 to SO2 (Left) Kanál 1 do SO2 (pravý) + Channel 2 to SO2 (Left) Kanál 2 do SO2 (pravý) + Channel 3 to SO2 (Left) Kanál 3 do SO2 (pravý) + Channel 4 to SO2 (Left) Kanál 4 do SO2 (pravý) + Channel 1 to SO1 (Right) Kanál 1 do SO1 (pravý) + Channel 2 to SO1 (Right) Kanál 2 do SO1 (pravý) + Channel 3 to SO1 (Right) Kanál 3 do SO1 (pravý) + Channel 4 to SO1 (Right) Kanál 4 do SO1 (pravý) + Treble Výšky + Bass Basy - - Shift Register width - Posun šířky registru - FreeBoyInstrumentView + Sweep Time: Trvání sweepu: + Sweep Time Trvání sweepu - Sweep RtShift amount: - Úroveň pro změnu frekvence sweepu: - - - Sweep RtShift amount - Úroveň pro změnu frekvence sweepu - - - Wave pattern duty: - Pracovní cyklus vlnového patternu: - - - Wave Pattern Duty - Pracovní cyklus vlnového patternu - - - Square Channel 1 Volume: - Hlasitost pulzního kanálu 1: - - - Length of each step in sweep: - Délka každého kroku ve sweepu: - - - Length of each step in sweep - Délka každého kroku ve sweepu - - - Wave pattern duty - Pracovní cyklus vlnového patternu - - - Square Channel 2 Volume: - Hlasitost pulzního kanálu 2: - - - Square Channel 2 Volume - Hlasitost pulzního kanálu 2 - - - Wave Channel Volume: - Hlasitost vlnového kanálu: - - - Wave Channel Volume - Hlasitost vlnového kanálu - - - Noise Channel Volume: - Hlasitost šumového kanálu: - - - Noise Channel Volume - Hlasitost šumového kanálu - - - SO1 Volume (Right): - Hlasitost SO1 (pravý): - - - SO1 Volume (Right) - Hlasitost SO1 (pravý) - - - SO2 Volume (Left): - Hlasitost SO2 (levý): - - - SO2 Volume (Left) - Hlasitost SO2 (levý) - - - Treble: - Výšky: - - - Treble - Výšky - - - Bass: - Basy: - - - Bass - Basy - - - Sweep Direction - Směr sweepu - - - Volume Sweep Direction - Směr hlasitosti sweepu - - - Shift Register Width - Posun šířky registru - - - Channel1 to SO1 (Right) - Kanál 1 do SO1 (pravý) - - - Channel2 to SO1 (Right) - Kanál 2 do SO1 (pravý) - - - Channel3 to SO1 (Right) - Kanál 3 do SO1 (pravý) - - - Channel4 to SO1 (Right) - Kanál 4 do SO1 (pravý) - - - Channel1 to SO2 (Left) - Kanál 1 do SO2 (levý) - - - Channel2 to SO2 (Left) - Kanál 2 do SO2 (levý) - - - Channel3 to SO2 (Left) - Kanál 3 do SO2 (levý) - - - Channel4 to SO2 (Left) - Kanál 4 do SO2 (levý) - - - Wave Pattern - Vlnový pattern - - + The amount of increase or decrease in frequency Množství zvýšení nebo snížení frekvence + + Sweep RtShift amount: + Úroveň pro změnu frekvence sweepu: + + + + Sweep RtShift amount + Úroveň pro změnu frekvence sweepu + + + The rate at which increase or decrease in frequency occurs Úroveň, při které dojde ke zvýšení nebo snížení frekvence + + + Wave pattern duty: + Pracovní cyklus vlnového patternu: + + + + Wave Pattern Duty + Pracovní cyklus vlnového patternu + + + + The duty cycle is the ratio of the duration (time) that a signal is ON versus the total period of the signal. Pracovní cyklus je poměr mezi dobou trvání (časem), kdy je signál zapnut, a celkovou délkou signálu. + + + Square Channel 1 Volume: + Hlasitost pulzního kanálu 1: + + + Square Channel 1 Volume Hlasitost pulzního kanálu 1 + + + + Length of each step in sweep: + Délka každého kroku ve sweepu: + + + + + + Length of each step in sweep + Délka každého kroku ve sweepu + + + + + The delay between step change Zpoždění mezi změnou kroku + + Wave pattern duty + Pracovní cyklus vlnového patternu + + + + Square Channel 2 Volume: + Hlasitost pulzního kanálu 2: + + + + + Square Channel 2 Volume + Hlasitost pulzního kanálu 2 + + + + Wave Channel Volume: + Hlasitost vlnového kanálu: + + + + + Wave Channel Volume + Hlasitost vlnového kanálu + + + + Noise Channel Volume: + Hlasitost šumového kanálu: + + + + + Noise Channel Volume + Hlasitost šumového kanálu + + + + SO1 Volume (Right): + Hlasitost SO1 (pravý): + + + + SO1 Volume (Right) + Hlasitost SO1 (pravý) + + + + SO2 Volume (Left): + Hlasitost SO2 (levý): + + + + SO2 Volume (Left) + Hlasitost SO2 (levý) + + + + Treble: + Výšky: + + + + Treble + Výšky + + + + Bass: + Basy: + + + + Bass + Basy + + + + Sweep Direction + Směr sweepu + + + + + + + + Volume Sweep Direction + Směr hlasitosti sweepu + + + + Shift Register Width + Posun šířky registru + + + + Channel1 to SO1 (Right) + Kanál 1 do SO1 (pravý) + + + + Channel2 to SO1 (Right) + Kanál 2 do SO1 (pravý) + + + + Channel3 to SO1 (Right) + Kanál 3 do SO1 (pravý) + + + + Channel4 to SO1 (Right) + Kanál 4 do SO1 (pravý) + + + + Channel1 to SO2 (Left) + Kanál 1 do SO2 (levý) + + + + Channel2 to SO2 (Left) + Kanál 2 do SO2 (levý) + + + + Channel3 to SO2 (Left) + Kanál 3 do SO2 (levý) + + + + Channel4 to SO2 (Left) + Kanál 4 do SO2 (levý) + + + + Wave Pattern + Vlnový pattern + + + Draw the wave here Nakreslete vlnu zde @@ -9361,34 +11704,42 @@ Poklepáním na kterýkoliv modul se zobrazí informace o portech. patchesDialog + Qsynth: Channel Preset Qsynth: Předvolba kanálu + Bank selector Výběr banky + Bank Banka + Program selector Výběr programu + Patch Patch + Name Název + OK OK + Cancel Zrušit @@ -9396,186 +11747,231 @@ Poklepáním na kterýkoliv modul se zobrazí informace o portech. pluginBrowser + no description bez popisu - Incomplete monophonic imitation tb303 - Nekompletní monofonní imitace tb303 + + A native amplifier plugin + Nativní plugin zesilovače - Plugin for freely manipulating stereo output - Plugin pro volné úpravy stereo výstupu + + Simple sampler with various settings for using samples (e.g. drums) in an instrument-track + Jednoduchý sampler s bohatým nastavením pro používání samplů (např. bicích nástrojů) v nástrojové stopě - Plugin for controlling knobs with sound peaks - Plugin pro řízení otočných ovladačů zvukovými špičkami + + Boost your bass the fast and simple way + Zesílení vašeho basu rychlým a snadným způsobem - Plugin for enhancing stereo separation of a stereo input file - Plugin pro zlepšení stereo separace vstupních stereo souborů + + Customizable wavetable synthesizer + Upravitelný tabulkový syntezátor + + An oversampling bitcrusher + Bitcrusher založený na převzorkování + + + + Carla Patchbay Instrument + Nástroj Carla Patchbay + + + + Carla Rack Instrument + Nástroj Carla Rack + + + + A 4-band Crossover Equalizer + 4 pásmový crossover ekvalizér + + + + A native delay plugin + Nativní plugin delay + + + + A Dual filter plugin + Plugin duální filtr + + + + plugin for processing dynamics in a flexible way + plugin pro flexibilní práci s dynamikou + + + + A native eq plugin + Nativní plugin ekvalizér + + + + A native flanger plugin + Nativní plugin flanger + + + + Player for GIG files + Přehrávač GIG souborů + + + + Filter for importing Hydrogen files into LMMS + Filtr pro import souborů Hydrogen do LMMS + + + + Versatile drum synthesizer + Univerzální syntezátor bicích nástrojů + + + List installed LADSPA plugins Seznam nainstalovaných LADSPA pluginů - GUS-compatible patch instrument - GUS kompatibilní patch instrument - - - Additive Synthesizer for organ-like sounds - Aditivní syntezátor pro zvuky podobné varhanám - - - Tuneful things to bang on - Melodické bicí nástroje - - - VST-host for using VST(i)-plugins within LMMS - VST host pro užití VST(i) pluginů v LMMS - - - Vibrating string modeler - Vibrační modelátor strun - - + plugin for using arbitrary LADSPA-effects inside LMMS. plugin pro užití libovolných LADSPA efektů uvnitř LMMS. + + Incomplete monophonic imitation tb303 + Nekompletní monofonní imitace tb303 + + + + Filter for exporting MIDI-files from LMMS + Filtr pro export souborů MIDI z LMMS + + + Filter for importing MIDI-files into LMMS Filtr pro import MIDI souborů do LMMS + + Monstrous 3-oscillator synth with modulation matrix + 3oscilátorový syntezátor Monstrous s modulační matricí + + + + A multitap echo delay plugin + Plugin multi-tap delay + + + + A NES-like synthesizer + Syntetizér typu NES + + + + 2-operator FM Synth + 2 operátorová FM syntéza + + + + Additive Synthesizer for organ-like sounds + Aditivní syntezátor pro zvuky podobné varhanám + + + + Emulation of GameBoy (TM) APU + Emulace APU GameBoye (TM) + + + + GUS-compatible patch instrument + GUS kompatibilní patch instrument + + + + Plugin for controlling knobs with sound peaks + Plugin pro řízení otočných ovladačů zvukovými špičkami + + + + Reverb algorithm by Sean Costello + Algoritmus dozvuku od Seana Costello + + + + Player for SoundFont files + Přehrávač SoundFont souborů + + + + LMMS port of sfxr + LMMS port sfxr + + + Emulation of the MOS6581 and MOS8580 SID. This chip was used in the Commodore 64 computer. Emulace MOS6581 a MOS8580 SID. Tento čip byl používán v počítačích Commodore 64. - Player for SoundFont files - Přehrávač SoundFont souborů - - - Emulation of GameBoy (TM) APU - Emulace APU GameBoye (TM) - - - Customizable wavetable synthesizer - Upravitelný tabulkový syntezátor - - - Embedded ZynAddSubFX - Vestavěný ZynAddSubFX - - - 2-operator FM Synth - 2 operátorová FM syntéza - - - Filter for importing Hydrogen files into LMMS - Filtr pro import souborů Hydrogen do LMMS - - - LMMS port of sfxr - LMMS port sfxr - - - Monstrous 3-oscillator synth with modulation matrix - 3oscilátorový syntezátor Monstrous s modulační matricí - - - Three powerful oscillators you can modulate in several ways - 3 silné oscilátory, které můžete různými způsoby modulovat - - - A native amplifier plugin - Nativní plugin zesilovače - - - Carla Rack Instrument - Nástroj Carla Rack - - - 4-oscillator modulatable wavetable synth - 4oscilátorový modulovatelný tabulkový syntezátor - - - plugin for waveshaping - plugin pro tvarování vln - - - Boost your bass the fast and simple way - Zesílení vašeho basu rychlým a snadným způsobem - - - Versatile drum synthesizer - Univerzální syntezátor bicích nástrojů - - - Simple sampler with various settings for using samples (e.g. drums) in an instrument-track - Jednoduchý sampler s bohatým nastavením pro používání samplů (např. bicích nástrojů) v nástrojové stopě - - - plugin for processing dynamics in a flexible way - plugin pro flexibilní práci s dynamikou - - - Carla Patchbay Instrument - Nástroj Carla Patchbay - - - plugin for using arbitrary VST effects inside LMMS. - Plugin pro použití libovolného VST efektu v LMMS. - - + Graphical spectrum analyzer plugin Plugin pro grafickou analýzu spektra - A NES-like synthesizer - Syntetizér typu NES + + Plugin for enhancing stereo separation of a stereo input file + Plugin pro zlepšení stereo separace vstupních stereo souborů - A native delay plugin - Nativní plugin delay + + Plugin for freely manipulating stereo output + Plugin pro volné úpravy stereo výstupu - Player for GIG files - Přehrávač GIG souborů + + Tuneful things to bang on + Melodické bicí nástroje - A multitap echo delay plugin - Plugin multi-tap delay + + Three powerful oscillators you can modulate in several ways + 3 silné oscilátory, které můžete různými způsoby modulovat - A native flanger plugin - Nativní plugin flanger + + VST-host for using VST(i)-plugins within LMMS + VST host pro užití VST(i) pluginů v LMMS - An oversampling bitcrusher - Bitcrusher založený na převzorkování + + Vibrating string modeler + Vibrační modelátor strun - A native eq plugin - Nativní plugin ekvalizér + + plugin for using arbitrary VST effects inside LMMS. + Plugin pro použití libovolného VST efektu v LMMS. - A 4-band Crossover Equalizer - 4 pásmový crossover ekvalizér + + 4-oscillator modulatable wavetable synth + 4oscilátorový modulovatelný tabulkový syntezátor - A Dual filter plugin - Plugin duální filtr + + plugin for waveshaping + plugin pro tvarování vln - Filter for exporting MIDI-files from LMMS - Filtr pro export souborů MIDI z LMMS - - - Reverb algorithm by Sean Costello - Algoritmus dozvuku od Seana Costello + + Embedded ZynAddSubFX + Vestavěný ZynAddSubFX Mathematical expression parser @@ -9585,58 +11981,72 @@ Tento čip byl používán v počítačích Commodore 64. sf2Instrument + Bank Banka + Patch Patch + Gain Zisk + Reverb Dozvuk + Reverb Roomsize Velikost dozvukového prostoru + Reverb Damping Útlum dozvuku + Reverb Width Délka dozvuku + Reverb Level Úroveň dozvuku + Chorus Chorus + Chorus Lines Počet linií chorusu + Chorus Level Úroveň chorusu + Chorus Speed Rychlost chorusu + Chorus Depth Hloubka chorusu + A soundfont %1 could not be loaded. Soundfont %1 nelze načíst. @@ -9644,74 +12054,92 @@ Tento čip byl používán v počítačích Commodore 64. sf2InstrumentView + Open other SoundFont file Otevřít jiný SoundFont soubor + Click here to open another SF2 file Klepněte sem pro otevření jiného SF2 souboru + Choose the patch Vybrat patch + Gain - Zisk + Zesílení + Apply reverb (if supported) Použít dozvuk (je-li podporován) + This button enables the reverb effect. This is useful for cool effects, but only works on files that support it. Tímto tlačítkem zapnete efekt dozvuk (reverb). Ten lze použít pro výborné efekty, ale funguje pouze se soubory, které jej podporují. + Reverb Roomsize: Velikost dozvukového prostoru: + Reverb Damping: Útlum dozvuku: + Reverb Width: Délka dozvuku: + Reverb Level: Úroveň dozvuku: + Apply chorus (if supported) Použít chorus (je-li podporován) + This button enables the chorus effect. This is useful for cool echo effects, but only works on files that support it. Tímto tlačítkem zapnete efekt chorus. Ten lze použít pro výborné echo efekty, ale funguje pouze se soubory, které jej podporují. + Chorus Lines: Počet linií chorusu: + Chorus Level: Úroveň chorusu: + Chorus Speed: Rychlost chorusu: + Chorus Depth: Hloubka chorusu: + Open SoundFont file Otevřít SoundFont soubor + SoundFont2 Files (*.sf2) Soubory SoundFont2 (*.sf2) @@ -9719,6 +12147,7 @@ Tento čip byl používán v počítačích Commodore 64. sfxrInstrument + Wave Form Vlna @@ -9726,26 +12155,32 @@ Tento čip byl používán v počítačích Commodore 64. sidInstrument + Cutoff Oříznutí + Resonance Rezonance + Filter type Typ filtru + Voice 3 off Vypnout hlas 3 + Volume Hlasitost + Chip model Model čipu @@ -9753,134 +12188,172 @@ Tento čip byl používán v počítačích Commodore 64. sidInstrumentView + Volume: Hlasitost: + Resonance: Rezonance: + + Cutoff frequency: Frekvence oříznutí: + High-Pass filter Filtr typu horní propust + Band-Pass filter Filtr typu pásmová propust + Low-Pass filter Filtr typu dolní propust + Voice3 Off Vypnout hlas 3 + MOS6581 SID MOS6581 SID + MOS8580 SID MOS8580 SID + + Attack: Náběh: + Attack rate determines how rapidly the output of Voice %1 rises from zero to peak amplitude. Rychlost náběhu určuje, jak rychle výstup hlasu %1 stoupne z nuly na špičkovou amplitudu. + + Decay: Útlum: + Decay rate determines how rapidly the output falls from the peak amplitude to the selected Sustain level. Rychlost útlumu (decay) určuje, jak rychle poklesne výstup ze špičky na zvolenou úroveň vydržení (sustain). + Sustain: Vydržení: + Output of Voice %1 will remain at the selected Sustain amplitude as long as the note is held. Výstup hlasu %1 zůstane na zvolené úrovni Vydržení po celou dobu, kdy bude nota držena. + + Release: Uvolnění: + The output of of Voice %1 will fall from Sustain amplitude to zero amplitude at the selected Release rate. Výstup hlasu %1 poklesne z úrovně vydržení (sustain) na nulovou amplitudu zvolenou rychlostí uvolnění (release). + + Pulse Width: Délka pulzu: + The Pulse Width resolution allows the width to be smoothly swept with no discernable stepping. The Pulse waveform on Oscillator %1 must be selected to have any audible effect. Rozlišení šířky pulsu umožňuje plynulé vyhlazení šířky, aby nebylo rozeznatelné krokování. Pulzní vlna na oscilátoru %1 musí být zvolena tak, aby měla slyšitelný efekt. + Coarse: Ladění: + The Coarse detuning allows to detune Voice %1 one octave up or down. Hrubé rozladění umožní rozladit hlas %1 až o jednu oktávu nahoru nebo dolů. + Pulse Wave Pulzní vlna + Triangle Wave Trojúhelníková vlna + SawTooth Pilovitá vlna + Noise Šum + Sync Synch + Sync synchronizes the fundamental frequency of Oscillator %1 with the fundamental frequency of Oscillator %2 producing "Hard Sync" effects. Synchronizace synchronizuje základní frekvenci oscilátoru %1 se základní frekvencí oscilátoru %2 pomocí efektu pevné (Hard Sync) synchronizace. + Ring-Mod Kruhová modulace + Ring-mod replaces the Triangle Waveform output of Oscillator %1 with a "Ring Modulated" combination of Oscillators %1 and %2. Kruhová modulace nahradí výstup trojúhelníkové vlny na oscilátoru %1 "kruhově modulovanou" kombinací oscilátorů %1 a %2. + Filtered Filtrování + When Filtered is on, Voice %1 will be processed through the Filter. When Filtered is off, Voice %1 appears directly at the output, and the Filter has no effect on it. Pokud je zapnuto filtrování, hlas %1 bude zpracován filtrem. Pokud je filtrování vypnuto, hlas %1 se objeví přímo na výstupu a filtr na něj nebude mít žádný efekt. + Test Test + Test, when set, resets and locks Oscillator %1 at zero until Test is turned off. Test, když je nastaven, resetuje a zablokuje oscilátor %1 na nule, dokud se test nevypne. @@ -9888,10 +12361,12 @@ Tento čip byl používán v počítačích Commodore 64. stereoEnhancerControlDialog + WIDE ŠÍŘKA + Width: Šířka: @@ -9899,6 +12374,7 @@ Tento čip byl používán v počítačích Commodore 64. stereoEnhancerControls + Width Šířka @@ -9906,18 +12382,22 @@ Tento čip byl používán v počítačích Commodore 64. stereoMatrixControlDialog + Left to Left Vol: Levý do levého – hlasitost: + Left to Right Vol: Levý do pravého – hlasitost: + Right to Left Vol: Pravý do levého – hlasitost: + Right to Right Vol: Pravý do pravého – hlasitost: @@ -9925,18 +12405,22 @@ Tento čip byl používán v počítačích Commodore 64. stereoMatrixControls + Left to Left Levý do levého + Left to Right Levý do pravého + Right to Left Pravý do levého + Right to Right Pravý do pravého @@ -9944,10 +12428,12 @@ Tento čip byl používán v počítačích Commodore 64. vestigeInstrument + Loading plugin Načítám plugin + Please wait while loading VST-plugin... Počkejte prosím, než se načte VST plugin... @@ -9955,42 +12441,52 @@ Tento čip byl používán v počítačích Commodore 64. vibed + String %1 volume Hlasitost struny %1 + String %1 stiffness Tvrdost struny %1 + Pick %1 position Místo drnknutí %1 + Pickup %1 position Umístění snímače %1 + Pan %1 Pan %1 + Detune %1 Rozladění %1 + Fuzziness %1 Roztřepení %1 + Length %1 Délka %1 + Impulse %1 Impulz %1 + Octave %1 Oktáva %1 @@ -9998,90 +12494,112 @@ Tento čip byl používán v počítačích Commodore 64. vibedView + Volume: Hlasitost: + The 'V' knob sets the volume of the selected string. Otočný ovladač "V" nastavuje hlasitost vybrané struny. + String stiffness: Tvrdost struny: + The 'S' knob sets the stiffness of the selected string. The stiffness of the string affects how long the string will ring out. The lower the setting, the longer the string will ring. Otočný ovladač "S" nastavuje tvrdost vybrané struny. Tvrdost struny ovlivňuje délku doznívání struny. Čím nižší hodnota, tím déle bude struna znít. + Pick position: Místo drnknutí: + The 'P' knob sets the position where the selected string will be 'picked'. The lower the setting the closer the pick is to the bridge. Otočný ovladač "P" nastavuje místo, ve kterém se na vybrané struně drnkne. Nižší nastavení znamená drnknutí blíže ke kobylce. + Pickup position: Pozice snímače: + The 'PU' knob sets the position where the vibrations will be monitored for the selected string. The lower the setting, the closer the pickup is to the bridge. Otočný ovladač "PU" nastavuje umístění snímače pro vybranou strunu. Nižší nastavení znamená snímač blíže u kobylky. + Pan: Panoráma: + The Pan knob determines the location of the selected string in the stereo field. Otočný ovladač "Pan" určuje pozici vybrané struny ve stereo prostoru. + Detune: Rozladění: + The Detune knob modifies the pitch of the selected string. Settings less than zero will cause the string to sound flat. Settings greater than zero will cause the string to sound sharp. Otočný ovladač "Detune" mění ladění vybrané struny. Hodnoty nižší než nula způsobí plochý zvuk, hodnoty vyšší než nula způsobí ostřejší zvuk. + Fuzziness: Roztřepení: + The Slap knob adds a bit of fuzz to the selected string which is most apparent during the attack, though it can also be used to make the string sound more 'metallic'. Otočný ovladač "Slap" přidává ke zvuku vybrané struny jemné roztřepení, které je nejvíce patrné při náběhu tónu, ačkoliv lze také použít pro vytvoření více "kovového" zvuku struny. + Length: Délka: + The Length knob sets the length of the selected string. Longer strings will both ring longer and sound brighter, however, they will also eat up more CPU cycles. Otočný ovladač "Lenght" nastavuje délku vybrané struny. Delší struny budou znít déle a jasněji, nicméně však spotřebují více CPU cyklů. + Impulse or initial state Impulz nebo výchozí stav + The 'Imp' selector determines whether the waveform in the graph is to be treated as an impulse imparted to the string by the pick or the initial state of the string. Přepínač "IMP" určuje, zda vlna v grafu bude považována za impulz přenášený na strunu drnknutím nebo za počáteční stav struny. + Octave Oktáva + The Octave selector is used to choose which harmonic of the note the string will ring at. For example, '-2' means the string will ring two octaves below the fundamental, 'F' means the string will ring at the fundamental, and '6' means the string will ring six octaves above the fundamental. Volič "Octave" se používá k výběru harmonického tónu, na kterém bude struna znít. Například "-2" znamená, že struna bude znít dvě oktávy pod základním tónem, "F" znamená, že zní základní tón a "6" znamená, že struna bude znít šest oktáv nad základním tónem. + Impulse Editor Editor impulzu + The waveform editor provides control over the initial state or impulse that is used to start the string vibrating. The buttons to the right of the graph will initialize the waveform to the selected type. The '?' button will load a waveform from a file--only the first 128 samples will be loaded. The waveform can also be drawn in the graph. @@ -10098,6 +12616,7 @@ Tlačítko "S" vyhladí vlnu. Tlačítko "N" normalizuje vlnu. + Vibed models up to nine independently vibrating strings. The 'String' selector allows you to choose which string is being edited. The 'Imp' selector chooses whether the graph represents an impulse or the initial state of the string. The 'Octave' selector chooses which harmonic the string should vibrate at. The graph allows you to control the initial state or impulse used to set the string in motion. @@ -10122,129 +12641,160 @@ Ovladač "Lenght" určuje délku struny. LED v pravém dolním rohu editoru vlny určuje, jestli bude struna v aktuálním nástroji aktivní. + Enable waveform Zapnout vlnu + Click here to enable/disable waveform. Klepněte sem pro zapnutí/vypnutí vlny. + String Struna + The String selector is used to choose which string the controls are editing. A Vibed instrument can contain up to nine independently vibrating strings. The LED in the lower right corner of the waveform editor indicates whether the selected string is active. Volič strun se užívá k výběru struny, které bude upravována. Nástroj Vibed může obsahovat maximálně devět nezávisle vibrujících strun. LED v pravém dolním rohu editoru tvaru vlny indikuje, zda je vybraná struna aktivní. + Sine wave Sinusová vlna - Triangle wave - Trojúhelníková vlna - - - Saw wave - Pilovitá vlna - - - Square wave - Pravoúhlá vlna - - - White noise wave - Bílý šum - - - User defined wave - Vlna definovaná uživatelem - - - Smooth - Vyhladit - - - Click here to smooth waveform. - Klepněte sem pro vyhlazení vlny. - - - Normalize - Normalizovat - - - Click here to normalize waveform. - Klepněte sem pro normalizaci vlny. - - + Use a sine-wave for current oscillator. Použít sinusovou vlnu pro aktuální oscilátor. + + Triangle wave + Trojúhelníková vlna + + + Use a triangle-wave for current oscillator. Použít trojúhelníkovou vlnu pro aktuální oscilátor. + + Saw wave + Pilovitá vlna + + + Use a saw-wave for current oscillator. - Klepněte sem pro pilovitou vlnu. + Použít pilovitou vlnu pro aktuální oscilátor. + + Square wave + Pravoúhlá vlna + + + Use a square-wave for current oscillator. - Klepněte sem pro pravoúhlou vlnu. + Použít pravoúhlou vlnu pro aktuální oscilátor. + + White noise wave + Bílý šum + + + Use white-noise for current oscillator. Použít bílý šum pro aktuální oscilátor. + + User defined wave + Vlna definovaná uživatelem + + + Use a user-defined waveform for current oscillator. Použít vlastní vlnu pro aktuální oscilátor. + + + Smooth + Vyhladit + + + + Click here to smooth waveform. + Klepněte sem pro vyhlazení vlny. + + + + Normalize + Normalizovat + + + + Click here to normalize waveform. + Klepněte sem pro normalizaci vlny. + voiceObject + Voice %1 pulse width Hlas %1 šířka pulzu + Voice %1 attack Hlas %1 náběh + Voice %1 decay Hlas %1 útlum + Voice %1 sustain Hlas %1 vydržení + Voice %1 release Hlas %1 uvolnění + Voice %1 coarse detuning Hlas %1 hrubé ladění + Voice %1 wave shape Hlas %1 tvar vlny + Voice %1 sync Hlas %1 synchronizace + Voice %1 ring modulate Hlas %1 kruhová modulace + Voice %1 filtered Hlas %1 filtrování + Voice %1 test Hlas %1 test @@ -10252,58 +12802,72 @@ LED v pravém dolním rohu editoru vlny určuje, jestli bude struna v aktuální waveShaperControlDialog + INPUT VSTUP + Input gain: Zesílení vstupu: + OUTPUT VÝSTUP + Output gain: Zesílení výstupu: + Reset waveform - Obnovit vlnu + Obnovení vlny + Click here to reset the wavegraph back to default Klepněte sem pro obnovení zobrazení křivky zpět do výchozího stavu + Smooth waveform - Vyhlazená vlna + Vyhlazení vlny + Click here to apply smoothing to wavegraph Klepněte sem pro vyhlazení křivky + Increase graph amplitude by 1dB Zvýši amplitudu grafu o 1dB + Click here to increase wavegraph amplitude by 1dB Klepněte sem pro zvýšení amplitudy křivky o 1 dB + Decrease graph amplitude by 1dB Snížit amplitudu grafu o 1dB + Click here to decrease wavegraph amplitude by 1dB Klepněte sem pro snížení amplitudy křivky o 1 dB + Clip input - Vstup klipu + Ořezat vstup + Clip input signal to 0dB Vstupní úroveň klipu 0dB @@ -10311,12 +12875,14 @@ LED v pravém dolním rohu editoru vlny určuje, jestli bude struna v aktuální waveShaperControls + Input gain Zesílení vstupu + Output gain Zesílení výstupu - \ No newline at end of file + diff --git a/data/locale/de.ts b/data/locale/de.ts index 63dc63ba5..d3957edf3 100644 --- a/data/locale/de.ts +++ b/data/locale/de.ts @@ -428,7 +428,7 @@ Wenn Sie daran interessiert sind LMMS in eine andere Sprache zu übersetzen oder A higher tension value may make a smoother curve but overshoot some values. A low tension value will cause the slope of the curve to level off at each control point. - Ein höherer Spannungswert erzeugt villeicht eine glattere Kurve aber schießt teilweise über. Ein niederer Spannungswert wird die Kurve über jeden Kontrollpunkt legen. + Ein höherer Spannungswert erzeugt vielleicht eine glattere Kurve aber schießt teilweise über. Ein niederer Spannungswert wird die Kurve über jeden Kontrollpunkt legen. Click here to choose discrete progressions for this automation pattern. The value of the connected object will remain constant between control points and be set immediately to the new value when each control point is reached. @@ -515,7 +515,7 @@ Wenn Sie daran interessiert sind LMMS in eine andere Sprache zu übersetzen oder AutomationPattern Drag a control while pressing <%1> - Ein Steuerelement mit <Strg> hier her ziehen + Ein Steuerelement mit <%1> hier her ziehen @@ -843,7 +843,7 @@ Wenn Sie daran interessiert sind LMMS in eine andere Sprache zu übersetzen oder USER CONTROLLER - BENUTZERDEFINIETER CONTROLLER + BENUTZERDEFINIERTER CONTROLLER MAPPING FUNCTION @@ -1030,7 +1030,7 @@ Wenn Sie daran interessiert sind LMMS in eine andere Sprache zu übersetzen oder DELAY - VERZÖGERUNG + DELAY FDBK @@ -1580,7 +1580,7 @@ Ein Recktsklick öffnet ein Kontextmenü, in dem Sie die Reihenfolge der Effekte Use this knob for setting modulation amount of the current LFO. The bigger this value the more the selected size (e.g. volume or cutoff-frequency) will be influenced by this LFO. - Benutzen Sie diesen Regler, um die Modulationsintensität des aktuellen LFOs einzustellen. Je größer der Wert, desto mehr wird die gewählte Größe (z.B. Lautstärke oder Cuttoff-Frequenz) von diesem LFO beeinflusst. + Benutzen Sie diesen Regler, um die Modulationsintensität des aktuellen LFOs einzustellen. Je größer der Wert, desto mehr wird die gewählte Größe (z.B. Lautstärke oder Cutoff-Frequenz) von diesem LFO beeinflusst. Click here for a sine-wave. @@ -2251,7 +2251,7 @@ Please make sure you have write permission to the file and the directory contain DELAY - VERZÖGERUNG + DELAY RATE @@ -2570,7 +2570,7 @@ Sie können FX Kanäle im Kontextmenü entfernen und verschieben, welches durch An arpeggio is a method playing (especially plucked) instruments, which makes the music much livelier. The strings of such instruments (e.g. harps) are plucked like chords. The only difference is that this is done in a sequential order, so the notes are not played at the same time. Typical arpeggios are major or minor triads, but there are a lot of other possible chords, you can select. - Ein Arpeggio ist eine Art, (vorallem gezupfte) Instrumente zu spielen, die die Musik viel lebendiger macht. Die Seiten von solchen Instrumenten (z.B. Harfen) werden wie Akkorde gezupft, der einzige Unterschied besteht darin, dass dies nacheinander geschieht. Die Noten werden also nicht zur gleichen Zeit gespielt. Typische Arpeggios sind Dur- oder Moll-Dreiklänge, aber es gibt noch viele andere Akkorde, die Sie auswählen können. + Ein Arpeggio ist eine Art, (vor allem gezupfte) Instrumente zu spielen, die die Musik viel lebendiger macht. Die Seiten von solchen Instrumenten (z.B. Harfen) werden wie Akkorde gezupft, der einzige Unterschied besteht darin, dass dies nacheinander geschieht. Die Noten werden also nicht zur gleichen Zeit gespielt. Typische Arpeggios sind Dur- oder Moll-Dreiklänge, aber es gibt noch viele andere Akkorde, die Sie auswählen können. RANGE @@ -2586,7 +2586,7 @@ Sie können FX Kanäle im Kontextmenü entfernen und verschieben, welches durch Use this knob for setting the arpeggio range in octaves. The selected arpeggio will be played within specified number of octaves. - Benutzen Sie diesen Regler, um den Arpeggio-Bereich in Oktaven zu setzen. Das gewähle Arpeggio wird innerhalb der angegebenen Anzahl von Oktaven abgespielt. + Benutzen Sie diesen Regler, um den Arpeggio-Bereich in Oktaven zu setzen. Das gewählte Arpeggio wird innerhalb der angegebenen Anzahl von Oktaven abgespielt. TIME @@ -3080,7 +3080,7 @@ Sie können FX Kanäle im Kontextmenü entfernen und verschieben, welches durch Use this knob for setting the chord range in octaves. The selected chord will be played within specified number of octaves. - Benutzen Sie diesen Regler, um den Akkord-Bereich in Oktaven zu setzen. Der gewähle Akkord wird innerhalb der angegebenen Anzahl von Oktaven abgespielt. + Benutzen Sie diesen Regler, um den Akkord-Bereich in Oktaven zu setzen. Der gewählte Akkord wird innerhalb der angegebenen Anzahl von Oktaven abgespielt. STACKING @@ -3485,7 +3485,7 @@ Sie können FX Kanäle im Kontextmenü entfernen und verschieben, welches durch Save current instrument track settings in a preset file - Aktuelle Instrumentenspur-Einstelungen in einer Presetdatei speichern + Aktuelle Instrumentenspur-Einstellungen in einer Presetdatei speichern Click here, if you want to save current instrument track settings in a preset file. Later you can load this preset by double-clicking it in the preset-browser. @@ -3680,7 +3680,7 @@ Sie können FX Kanäle im Kontextmenü entfernen und verschieben, welches durch Use this knob for setting modulation amount of the LFO. The bigger this value, the more the connected control (e.g. volume or cutoff-frequency) will be influenced by the LFO. - Benutzen Sie diesen Regler, um die Modulationsintensität des LFOs einzustellen. Je größer der Wert, desto mehr wird die gewählte Größe (z.B. Lautstärke oder Cuttoff-Frequenz) von diesem LFO beeinflusst. + Benutzen Sie diesen Regler, um die Modulationsintensität des LFOs einzustellen. Je größer der Wert, desto mehr wird die gewählte Größe (z.B. Lautstärke oder Cutoff-Frequenz) von diesem LFO beeinflusst. PHS @@ -3978,7 +3978,11 @@ Bitte besuchen Sie http://lmms.sf.net/wiki für Dokumentationen über LMMS. E&xport Tracks... - E&xport Tracks... + Tracks e&xportieren... + + + Export &MIDI... + &MIDI exportieren... Online Help @@ -3998,7 +4002,7 @@ Bitte besuchen Sie http://lmms.sf.net/wiki für Dokumentationen über LMMS. Project recovery - Project wiederherstellen + Projekt wiederherstellen There is a recovery file present. It looks like the last session did not end properly or another instance of LMMS is already running. Do you want to recover the project of this session? @@ -4026,11 +4030,11 @@ Bitte besuchen Sie http://lmms.sf.net/wiki für Dokumentationen über LMMS. Preparing file browsers - Dateimanger vorbereiten + Dateimanager vorbereiten Root directory - Grundverzeichniss + Grundverzeichnis Loading background artwork @@ -4289,7 +4293,7 @@ Please make sure you have write permission to the file and the directory contain Osc 1 Pulse width - Oszilator 1 Pulsweite + Oszillator 1 Pulsweite Osc 1 Sync send on rise @@ -4649,7 +4653,7 @@ Please make sure you have write permission to the file and the directory contain Bandlimited Triangle wave - Bandlimittierte Dreieckwelle + Bandlimitierte Dreieckwelle Bandlimited Saw wave @@ -4816,11 +4820,11 @@ Jedes Modulationsziel hat 4 Regler, einen für jeden Modulator. Standardmäßig Hard sync: Every time the oscillator receives a sync signal from oscillator 1, its phase is reset to 0 + whatever its phase offset is. - Hard sync: Jedes Mal, wenn der Oszillator ein sync-Signal von Oszillator 1 empfäng, wird die Phase auf 0 zurückgesetzt, egal was die Phasendifferenz ist. + Hard sync: Jedes Mal, wenn der Oszillator ein sync-Signal von Oszillator 1 empfängt, wird die Phase auf 0 zurückgesetzt, egal was die Phasendifferenz ist. Reverse sync: Every time the oscillator receives a sync signal from oscillator 1, the amplitude of the oscillator gets inverted. - Reverse sync: Jedes Mal, wenn der Oszillator ein sync-Signal von Oszillator 1 empfäng, wird die Amplitude des Oszillators invertiert. + Reverse sync: Jedes Mal, wenn der Oszillator ein sync-Signal von Oszillator 1 empfängt, wird die Amplitude des Oszillators invertiert. Choose waveform for oscillator 2. @@ -4912,7 +4916,7 @@ PM bedeutet Phasen-Modulation: Die Phase von Oszillator 3 wird durch Oszillator SUS, or sustain, controls the sustain level of the envelope. The decay phase will not go below this level as long as the note is held. - SUS, oder Dauerpegel, kontrolliert den Dauerpgel der Hüllkurve. Die Abfall-Phase geht nicht unter diesen Pegel, solange die Note gehalten wird. + SUS, oder Dauerpegel, kontrolliert den Dauerpegel der Hüllkurve. Die Abfall-Phase geht nicht unter diesen Pegel, solange die Note gehalten wird. REL, or release, controls how long the release is for the note, measured in how long it would take to fall from peak to zero. Actual release may be shorter, depending on at what phase the note is released. @@ -5436,7 +5440,7 @@ PM bedeutet Phasen-Modulation: Die Phase von Oszillator 3 wird durch Oszillator Due to a bug in older version of LMMS, the peak controllers may not be connect properly. Please ensure that peak controllers are connected properly and re-save this file. Sorry for any inconvenience caused. - Aufgrud eines Fehlers in einer älteren Version von LMMS, sind die Peak Controller möglicherweise nicht richtig verbunden. Bitte stellen Sie sicher, dass die Peak Controller richtig verbunden sind und speichern Sie die Datei erneut. Entschuldigung für jegliche verursachte Unannehmlichkeiten. + Aufgrund eines Fehlers in einer älteren Version von LMMS, sind die Peak Controller möglicherweise nicht richtig verbunden. Bitte stellen Sie sicher, dass die Peak Controller richtig verbunden sind und speichern Sie die Datei erneut. Entschuldigung für jegliche verursachte Unannehmlichkeiten. @@ -6133,7 +6137,7 @@ Grund: »%2« Mute/unmute (<%1> + middle click) - Stumm/Laut schalten (<Strg> + Mittelklick) + Stumm/Laut schalten (<%1> + Mittelklick) @@ -6376,19 +6380,19 @@ Latenz: %2 ms Themes directory - Themen Verzeichniss + Themen Verzeichnis GIG directory - GIG Verzeichniss + GIG Verzeichnis SF2 directory - SF2 Verzeichniss + SF2 Verzeichnis LADSPA plugin directories - LADSPA Plugin Verzeichniss + LADSPA Plugin Verzeichnisse Auto save @@ -6968,7 +6972,7 @@ Bitte stellen Sie sicher, dass Sie Leserechte auf diese Datei sowie das Verzeich Mute/unmute (<%1> + middle click) - Stumm/Laut schalten (<Strg> + Mittelklick) + Stumm/Laut schalten (<%1> + Mittelklick) @@ -7515,19 +7519,19 @@ Bitte stellen Sie sicher, dass Sie Leserechte auf diese Datei sowie das Verzeich WatsynView Select oscillator A1 - Oszilator A1 auswählen + Oszillator A1 auswählen Select oscillator A2 - Oszilator A2 auswählen + Oszillator A2 auswählen Select oscillator B1 - Oszilator B1 auswählen + Oszillator B1 auswählen Select oscillator B2 - Oszilator B2 auswählen + Oszillator B2 auswählen Mix output of A2 to A1 @@ -8570,7 +8574,7 @@ Doppelklicken auf eines der Plugins zeigt Informaitonen über die Ports an. Bandlimited triangle wave - Bandlimittierte Dreieckwelle + Bandlimitierte Dreieckwelle Click here for bandlimited triangle wave. @@ -8909,7 +8913,7 @@ Doppelklicken auf eines der Plugins zeigt Informaitonen über die Ports an. Op 1 Level - Op 1 Strärke + Op 1 Stärke Op 1 Level Scaling @@ -8961,7 +8965,7 @@ Doppelklicken auf eines der Plugins zeigt Informaitonen über die Ports an. Op 2 Level - Op 2 Strärke + Op 2 Stärke Op 2 Level Scaling @@ -9867,7 +9871,7 @@ Dieser Chip wurde in Commodore 64 Computern genutzt. When Filtered is on, Voice %1 will be processed through the Filter. When Filtered is off, Voice %1 appears directly at the output, and the Filter has no effect on it. - Wenn gefilter an ist, wird Stimme %1 durch den Filter verarbeitet. Wenn gefiltert aus ist, wird Stimme %1 direckt an die Ausgabe weitergeleitet und der Filter hat keine Auswirkung darauf. + Wenn gefilter an ist, wird Stimme %1 durch den Filter verarbeitet. Wenn gefiltert aus ist, wird Stimme %1 direkt an die Ausgabe weitergeleitet und der Filter hat keine Auswirkung darauf. Test @@ -10064,7 +10068,7 @@ Dieser Chip wurde in Commodore 64 Computern genutzt. Octave - Okatve + Oktave The Octave selector is used to choose which harmonic of the note the string will ring at. For example, '-2' means the string will ring two octaves below the fundamental, 'F' means the string will ring at the fundamental, and '6' means the string will ring six octaves above the fundamental. @@ -10312,4 +10316,4 @@ Die LED rechts unterhalb der Wellenform gibt an, ob die Saite aktiviert ist.Ausgabeverstärkung - \ No newline at end of file + diff --git a/data/locale/en.ts b/data/locale/en.ts index 253bf4a57..f20bfaac2 100644 --- a/data/locale/en.ts +++ b/data/locale/en.ts @@ -153,105 +153,59 @@ If you're interested in translating LMMS in another language or want to imp AudioFileProcessorView - Open other sample + Open sample - - Click here, if you want to open another audio-file. A dialog will appear where you can select your file. Settings like looping-mode, start and end-points, amplify-value, and so on are not reset. So, it may not sound like the original sample. - - - - + Reverse sample - - If you enable this button, the whole sample is reversed. This is useful for cool effects, e.g. a reversed crash. - - - - + Disable loop - - This button disables looping. The sample plays only once from start to end. - - - - - + Enable loop - - This button enables forwards-looping. The sample loops between the end point and the loop point. + + Enable ping-pong loop - - This button enables ping-pong-looping. The sample loops backwards and forwards between the end point and the loop point. - - - - + Continue sample playback across notes - - Enabling this option makes the sample continue playing across different notes - if you change pitch, or the note length stops before the end of the sample, then the next note played will continue where it left off. To reset the playback to the start of the sample, insert a note at the bottom of the keyboard (< 20 Hz) - - - - + Amplify: - - With this knob you can set the amplify ratio. When you set a value of 100% your sample isn't changed. Otherwise it will be amplified up or down (your actual sample-file isn't touched!) + + Start point: - - Startpoint: + + End point: - - With this knob you can set the point where AudioFileProcessor should begin playing your sample. - - - - - Endpoint: - - - - - With this knob you can set the point where AudioFileProcessor should stop playing your sample. - - - - + Loopback point: - - - With this knob you can set the point where the loop starts. - - AudioFileProcessorWaveView - + Sample length: @@ -259,38 +213,38 @@ If you're interested in translating LMMS in another language or want to imp AudioJack - + JACK client restarted - + LMMS was kicked by JACK for some reason. Therefore the JACK backend of LMMS has been restarted. You will have to make manual connections again. - + JACK server down - + The JACK server seems to have been shutdown and starting a new instance failed. Therefore LMMS is unable to proceed. You should save your project and restart JACK and LMMS. - + CLIENT-NAME - + CHANNELS - AudioOss::setupWidget + AudioOss DEVICE @@ -305,25 +259,25 @@ If you're interested in translating LMMS in another language or want to imp AudioPortAudio::setupWidget - + BACKEND - + DEVICE - AudioPulseAudio::setupWidget + AudioPulseAudio - + DEVICE - + CHANNELS @@ -331,13 +285,13 @@ If you're interested in translating LMMS in another language or want to imp AudioSdl::setupWidget - + DEVICE - AudioSndio::setupWidget + AudioSndio DEVICE @@ -352,12 +306,12 @@ If you're interested in translating LMMS in another language or want to imp AudioSoundIo::setupWidget - + BACKEND - + DEVICE @@ -365,62 +319,62 @@ If you're interested in translating LMMS in another language or want to imp AutomatableModel - + &Reset (%1%2) - + &Copy value (%1%2) - + &Paste value (%1%2) - + &Paste value - + Edit song-global automation - + Remove song-global automation - + Remove all linked controls - + Connected to %1 - + Connected to controller - + Edit connection... - + Remove connection - + Connect to controller... @@ -428,17 +382,17 @@ If you're interested in translating LMMS in another language or want to imp AutomationEditor - + Please open an automation pattern with the context menu of a control! - + Values copied - + All selected values were copied to the clipboard. @@ -446,184 +400,124 @@ If you're interested in translating LMMS in another language or want to imp AutomationEditorWindow - + Play/pause current pattern (Space) - - Click here if you want to play the current pattern. This is useful while editing it. The pattern is automatically looped when the end is reached. - - - - + Stop playing of current pattern (Space) - - Click here if you want to stop playing of the current pattern. - - - - + Edit actions - + Draw mode (Shift+D) - + Erase mode (Shift+E) - + Flip vertically - + Flip horizontally - - Click here and the pattern will be inverted.The points are flipped in the y direction. - - - - - Click here and the pattern will be reversed. The points are flipped in the x direction. - - - - - Click here and draw-mode will be activated. In this mode you can add and move single values. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. - - - - - Click here and erase-mode will be activated. In this mode you can erase single values. You can also press 'Shift+E' on your keyboard to activate this mode. - - - - + Interpolation controls - + Discrete progression - + Linear progression - + Cubic Hermite progression - + Tension value for spline - - A higher tension value may make a smoother curve but overshoot some values. A low tension value will cause the slope of the curve to level off at each control point. - - - - - Click here to choose discrete progressions for this automation pattern. The value of the connected object will remain constant between control points and be set immediately to the new value when each control point is reached. - - - - - Click here to choose linear progressions for this automation pattern. The value of the connected object will change at a steady rate over time between control points to reach the correct value at each control point without a sudden change. - - - - - Click here to choose cubic hermite progressions for this automation pattern. The value of the connected object will change in a smooth curve and ease in to the peaks and valleys. - - - - + Tension: - + Cut selected values (%1+X) - + Copy selected values (%1+C) - + Paste values from clipboard (%1+V) - - Click here and selected values will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. - - - - - Click here and selected values will be copied into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. - - - - - Click here and the values from the clipboard will be pasted at the first visible measure. - - - - + Zoom controls - + + Horizontal zooming + + + + + Vertical zooming + + + + Quantization controls - + Quantization - - Quantization. Sets the smallest step size for the Automation Point. By default this also sets the length, clearing out other points in the range. Press <Ctrl> to override this behaviour. - - - - - + + Automation Editor - no pattern - - + + Automation Editor - %1 - + Model is already connected to this pattern. @@ -631,7 +525,7 @@ If you're interested in translating LMMS in another language or want to imp AutomationPattern - + Drag a control while pressing <%1> @@ -715,52 +609,42 @@ If you're interested in translating LMMS in another language or want to imp - - Click here to play the current beat/bassline. The beat/bassline is automatically looped when its end is reached. - - - - - Click here to stop playing of current beat/bassline. - - - - + Beat selector - + Track and step actions - + Add beat/bassline - + Add sample-track - + Add automation-track - + Remove steps - + Add steps - + Clone Steps @@ -768,27 +652,27 @@ If you're interested in translating LMMS in another language or want to imp BBTCOView - + Open in Beat+Bassline-Editor - + Reset name - + Change name - + Change color - + Reset color to default @@ -796,12 +680,12 @@ If you're interested in translating LMMS in another language or want to imp BBTrack - + Beat/Bassline %1 - + Clone of %1 @@ -877,7 +761,7 @@ If you're interested in translating LMMS in another language or want to imp - Input Gain: + Input gain: @@ -887,12 +771,12 @@ If you're interested in translating LMMS in another language or want to imp - Input Noise: + Input noise: - Output Gain: + Output gain: @@ -902,27 +786,27 @@ If you're interested in translating LMMS in another language or want to imp - Output Clip: + Output clip: - Rate Enabled + Rate enabled - Enable samplerate-crushing + Enable sample-rate crushing - Depth Enabled + Depth enabled - Enable bitdepth-crushing + Enable bit-depth crushing @@ -957,30 +841,60 @@ If you're interested in translating LMMS in another language or want to imp - CaptionMenu + BitcrushControls - - &Help + + Input gain - - Help (not available) + + Input noise + + + + + Output gain + + + + + Output clip + + + + + Sample rate + + + + + Stereo difference + + + + + Levels + + + + + Rate enabled + + + + + Depth enabled CarlaInstrumentView - + Show GUI - - - Click here to show or hide the graphical user interface (GUI) of Carla. - - Controller @@ -1039,27 +953,27 @@ If you're interested in translating LMMS in another language or want to imp - + MAPPING FUNCTION - + OK - + Cancel - + LMMS - + Cycle Detected. @@ -1090,37 +1004,32 @@ If you're interested in translating LMMS in another language or want to imp ControllerView - + Controls - - Controllers are able to automate the value of a knob, slider, and other controls. - - - - + Rename controller - + Enter the new name for this controller - + LFO - + &Remove this controller - + Re&name this controller @@ -1129,77 +1038,97 @@ If you're interested in translating LMMS in another language or want to imp CrossoverEQControlDialog - Band 1/2 Crossover: + Band 1/2 crossover: - Band 2/3 Crossover: + Band 2/3 crossover: - Band 3/4 Crossover: + Band 3/4 crossover: + + + + + Band 1 gain - Band 1 Gain: + Band 1 gain: + + + + + Band 2 gain - Band 2 Gain: + Band 2 gain: + + + + + Band 3 gain - Band 3 Gain: + Band 3 gain: + + + + + Band 4 gain - Band 4 Gain: + Band 4 gain: - Band 1 Mute + Band 1 mute - Mute Band 1 + Mute band 1 - Band 2 Mute + Band 2 mute - Mute Band 2 + Mute band 2 - Band 3 Mute + Band 3 mute - Mute Band 3 + Mute band 3 - Band 4 Mute + Band 4 mute - Mute Band 4 + Mute band 4 @@ -1207,7 +1136,7 @@ If you're interested in translating LMMS in another language or want to imp DelayControls - Delay Samples + Delay samples @@ -1217,12 +1146,12 @@ If you're interested in translating LMMS in another language or want to imp - Lfo Frequency + LFO frequency - Lfo Amount + LFO amount @@ -1240,7 +1169,7 @@ If you're interested in translating LMMS in another language or want to imp - Delay Time + Delay time @@ -1250,7 +1179,7 @@ If you're interested in translating LMMS in another language or want to imp - Feedback Amount + Feedback amount @@ -1260,7 +1189,7 @@ If you're interested in translating LMMS in another language or want to imp - Lfo + LFO frequency @@ -1270,12 +1199,12 @@ If you're interested in translating LMMS in another language or want to imp - Lfo Amt + LFO amount - Out Gain + Out gain @@ -1344,12 +1273,12 @@ If you're interested in translating LMMS in another language or want to imp - Click to enable/disable Filter 1 + Enable/disable filter 1 - Click to enable/disable Filter 2 + Enable/disable filter 2 @@ -1367,7 +1296,7 @@ If you're interested in translating LMMS in another language or want to imp - Cutoff 1 frequency + Cutoff frequency 1 @@ -1397,7 +1326,7 @@ If you're interested in translating LMMS in another language or want to imp - Cutoff 2 frequency + Cutoff frequency 2 @@ -1413,25 +1342,25 @@ If you're interested in translating LMMS in another language or want to imp - LowPass + Low-pass - HiPass + Hi-pass - BandPass csg + Band-pass csg - BandPass czpg + Band-pass czpg @@ -1443,7 +1372,7 @@ If you're interested in translating LMMS in another language or want to imp - Allpass + All-pass @@ -1455,49 +1384,49 @@ If you're interested in translating LMMS in another language or want to imp - 2x LowPass + 2x Low-pass - RC LowPass 12dB + RC Low-pass 12 dB/oct - RC BandPass 12dB + RC Band-pass 12 dB/oct - RC HighPass 12dB + RC High-pass 12 dB/oct - RC LowPass 24dB + RC Low-pass 24 dB/oct - RC BandPass 24dB + RC Band-pass 24 dB/oct - RC HighPass 24dB + RC High-pass 24 dB/oct - Vocal Formant Filter + Vocal Formant @@ -1509,19 +1438,19 @@ If you're interested in translating LMMS in another language or want to imp - SV LowPass + SV Low-pass - SV BandPass + SV Band-pass - SV HighPass + SV High-pass @@ -1546,50 +1475,55 @@ If you're interested in translating LMMS in another language or want to imp Editor - + Transport controls - + Play (Space) - + Stop (Space) - + Record - + Record while playing + + + Toggle Step Recording + + Effect - + Effect enabled - + Wet/Dry mix - + Gate - + Decay @@ -1623,23 +1557,23 @@ If you're interested in translating LMMS in another language or want to imp - - + + Name - + Type - + Description - + Author @@ -1647,94 +1581,57 @@ If you're interested in translating LMMS in another language or want to imp EffectView - - Toggles the effect on or off. - - - - + On/Off - + W/D - + Wet Level: - - The Wet/Dry knob sets the ratio between the input signal and the effect signal that forms the output. - - - - + DECAY - + Time: - - The Decay knob controls how many buffers of silence must pass before the plugin stops processing. Smaller values will reduce the CPU overhead but run the risk of clipping the tail on delay and reverb effects. - - - - + GATE - + Gate: - - The Gate knob controls the signal level that is considered to be 'silence' while deciding when to stop processing signals. - - - - + Controls - - Effect plugins function as a chained series of effects where the signal will be processed from top to bottom. - -The On/Off switch allows you to bypass a given plugin at any point in time. - -The Wet/Dry knob controls the balance between the input signal and the effected signal that is the resulting output from the effect. The input for the stage is the output from the previous stage. So, the 'dry' signal for effects lower in the chain contains all of the previous effects. - -The Decay knob controls how long the signal will continue to be processed after the notes have been released. The effect will stop processing signals when the volume has dropped below a given threshold for a given length of time. This knob sets the 'given length of time'. Longer times will require more CPU, so this number should be set low for most effects. It needs to be bumped up for effects that produce lengthy periods of silence, e.g. delays. - -The Gate knob controls the 'given threshold' for the effect's auto shutdown. The clock for the 'given length of time' will begin as soon as the processed signal level drops below the level specified with this knob. - -The Controls button opens a dialog for editing the effect's parameters. - -Right clicking will bring up a context menu where you can change the order in which the effects are processed or delete an effect altogether. - - - - + Move &up - + Move &down - + &Remove this plugin @@ -1743,72 +1640,72 @@ Right clicking will bring up a context menu where you can change the order in wh EnvelopeAndLfoParameters - Predelay + Env pre-delay - Attack + Env attack - Hold + Env hold - Decay + Env decay - Sustain + Env sustain - Release + Env release - Modulation + Env mod amount - LFO Predelay + LFO pre-delay - LFO Attack + LFO attack - LFO speed + LFO frequency - LFO Modulation + LFO mod amount - LFO Wave Shape + LFO wave shape - Freq x 100 + LFO frequency x 100 - Modulate Env-Amount + Modulate env amount @@ -1816,226 +1713,123 @@ Right clicking will bring up a context menu where you can change the order in wh EnvelopeAndLfoView - + DEL - Predelay: + + Pre-delay: - - Use this knob for setting predelay of the current envelope. The bigger this value the longer the time before start of actual envelope. - - - - - + + ATT - + + Attack: - - Use this knob for setting attack-time of the current envelope. The bigger this value the longer the envelope needs to increase to attack-level. Choose a small value for instruments like pianos and a big value for strings. - - - - + HOLD - + Hold: - - Use this knob for setting hold-time of the current envelope. The bigger this value the longer the envelope holds attack-level before it begins to decrease to sustain-level. - - - - + DEC - + Decay: - - Use this knob for setting decay-time of the current envelope. The bigger this value the longer the envelope needs to decrease from attack-level to sustain-level. Choose a small value for instruments like pianos. - - - - + SUST - + Sustain: - - Use this knob for setting sustain-level of the current envelope. The bigger this value the higher the level on which the envelope stays before going down to zero. - - - - + REL - + Release: - - Use this knob for setting release-time of the current envelope. The bigger this value the longer the envelope needs to decrease from sustain-level to zero. Choose a big value for soft instruments like strings. - - - - - + + AMT - - + + Modulation amount: - - Use this knob for setting modulation amount of the current envelope. The bigger this value the more the according size (e.g. volume or cutoff-frequency) will be influenced by this envelope. - - - - - LFO predelay: - - - - - Use this knob for setting predelay-time of the current LFO. The bigger this value the the time until the LFO starts to oscillate. - - - - - LFO- attack: - - - - - Use this knob for setting attack-time of the current LFO. The bigger this value the longer the LFO needs to increase its amplitude to maximum. - - - - + SPD - - LFO speed: + + Frequency: - - Use this knob for setting speed of the current LFO. The bigger this value the faster the LFO oscillates and the faster will be your effect. - - - - - Use this knob for setting modulation amount of the current LFO. The bigger this value the more the selected size (e.g. volume or cutoff-frequency) will be influenced by this LFO. - - - - - Click here for a sine-wave. - - - - - Click here for a triangle-wave. - - - - - Click here for a saw-wave for current. - - - - - Click here for a square-wave. - - - - - Click here for a user-defined wave. Afterwards, drag an according sample-file onto the LFO graph. - - - - - Click here for random wave. - - - - + FREQ x 100 - - Click here if the frequency of this LFO should be multiplied by 100. + + Multiply LFO frequency by 100 - - multiply LFO-frequency by 100 + + MODULATE ENV AMOUNT - - MODULATE ENV-AMOUNT + + Control envelope amount by this LFO - - Click here to make the envelope-amount controlled by this LFO. - - - - - control envelope-amount by this LFO - - - - + ms/LFO: - + Hint - - Drag a sample from somewhere and drop it in this window. + + Drag and drop a sample into this window. @@ -2053,7 +1847,7 @@ Right clicking will bring up a context menu where you can change the order in wh - Low shelf gain + Low-shelf gain @@ -2078,7 +1872,7 @@ Right clicking will bring up a context menu where you can change the order in wh - High Shelf gain + High-shelf gain @@ -2088,7 +1882,7 @@ Right clicking will bring up a context menu where you can change the order in wh - Low Shelf res + Low-shelf res @@ -2113,7 +1907,7 @@ Right clicking will bring up a context menu where you can change the order in wh - High Shelf res + High-shelf res @@ -2128,7 +1922,7 @@ Right clicking will bring up a context menu where you can change the order in wh - Low Shelf freq + Low-shelf freq @@ -2153,7 +1947,7 @@ Right clicking will bring up a context menu where you can change the order in wh - High shelf freq + High-shelf freq @@ -2168,7 +1962,7 @@ Right clicking will bring up a context menu where you can change the order in wh - Low shelf active + Low-shelf active @@ -2193,7 +1987,7 @@ Right clicking will bring up a context menu where you can change the order in wh - High shelf active + High-shelf active @@ -2233,12 +2027,12 @@ Right clicking will bring up a context menu where you can change the order in wh - low pass type + Low-pass type - high pass type + High-pass type @@ -2261,7 +2055,7 @@ Right clicking will bring up a context menu where you can change the order in wh - Low Shelf + Low-shelf @@ -2286,7 +2080,7 @@ Right clicking will bring up a context menu where you can change the order in wh - High Shelf + High-shelf @@ -2296,7 +2090,7 @@ Right clicking will bring up a context menu where you can change the order in wh - In Gain + Input gain @@ -2308,7 +2102,7 @@ Right clicking will bring up a context menu where you can change the order in wh - Out Gain + Output gain @@ -2333,12 +2127,12 @@ Right clicking will bring up a context menu where you can change the order in wh - lp grp + LP group - hp grp + HP group @@ -2379,192 +2173,202 @@ Right clicking will bring up a context menu where you can change the order in wh - + + Render Looped Section: + + + + + time(s) + + + + File format settings - + File format: - + Sampling rate: - + 44100 Hz - + 48000 Hz - + 88200 Hz - + 96000 Hz - + 192000 Hz - + Bit depth: - + 16 Bit integer - + 24 Bit integer - + 32 Bit float - + Stereo mode: - + Mono - + Stereo - + Joint stereo - + Compression level: - + Bitrate: - + 64 KBit/s - + 128 KBit/s - + 160 KBit/s - + 192 KBit/s - + 256 KBit/s - + 320 KBit/s - + Use variable bitrate - + Quality settings - + Interpolation: - + Zero order hold - + Sinc worst (fastest) - + Sinc medium (recommended) - + Sinc best (slowest) - + Oversampling: - + 1x (None) - + 2x - + 4x - + 8x - + Start - + Cancel @@ -2595,17 +2399,17 @@ Please make sure you have write permission to the file and the directory contain - + Error - + Error while determining file-encoder device. Please try to choose a different output format. - + Rendering: %1% @@ -2613,14 +2417,14 @@ Please make sure you have write permission to the file and the directory contain Fader - - + + Set value - - + + Please enter a new value between %1 and %2: @@ -2638,7 +2442,7 @@ Please make sure you have write permission to the file and the directory contain - + Refresh list @@ -2646,47 +2450,47 @@ Please make sure you have write permission to the file and the directory contain FileBrowserTreeWidget - + Send to active instrument-track - + Open in new instrument-track/Song Editor - + Open in new instrument-track/B+B Editor - + Loading sample - + Please wait, loading sample for preview... - + Error - + does not appear to be a valid - + file - + --- Factory files --- @@ -2695,12 +2499,12 @@ Please make sure you have write permission to the file and the directory contain FlangerControls - Delay Samples + Delay samples - Lfo Frequency + LFO frequency @@ -2733,7 +2537,7 @@ Please make sure you have write permission to the file and the directory contain - Delay Time: + Delay time: @@ -2763,7 +2567,7 @@ Please make sure you have write permission to the file and the directory contain - Feedback Amount: + Feedback amount: @@ -2773,7 +2577,7 @@ Please make sure you have write permission to the file and the directory contain - White Noise Amount: + White noise amount: @@ -2785,425 +2589,391 @@ Please make sure you have write permission to the file and the directory contain FreeBoyInstrument - + Sweep time - + Sweep direction - - - Sweep RtShift amount - - - - Wave Pattern Duty + Sweep rate shift amount - Channel 1 volume + + Wave pattern duty cycle - - - Volume sweep direction + Channel 1 volume + Volume sweep direction + + + + + + Length of each step in sweep - + Channel 2 volume - + Channel 3 volume - + Channel 4 volume - + Shift Register width - - - Right Output level - - - - - Left Output level - - - Channel 1 to SO2 (Left) + Right output level - Channel 2 to SO2 (Left) + Left output level - Channel 3 to SO2 (Left) + Channel 1 to SO2 (Left) - Channel 4 to SO2 (Left) + Channel 2 to SO2 (Left) - Channel 1 to SO1 (Right) + Channel 3 to SO2 (Left) - Channel 2 to SO1 (Right) + Channel 4 to SO2 (Left) - Channel 3 to SO1 (Right) + Channel 1 to SO1 (Right) - Channel 4 to SO1 (Right) + Channel 2 to SO1 (Right) - Treble + Channel 3 to SO1 (Right) + Channel 4 to SO1 (Right) + + + + + Treble + + + + Bass FreeBoyInstrumentView - - - Sweep Time: - - - Sweep Time + Sweep time: - - The amount of increase or decrease in frequency + + Sweep time - Sweep RtShift amount: + Sweep rate shift amount: - Sweep RtShift amount + Sweep rate shift amount - - The rate at which increase or decrease in frequency occurs + + + Wave pattern duty cycle: - - - Wave pattern duty: - - - - - Wave Pattern Duty + + + Wave pattern duty cycle - - The duty cycle is the ratio of the duration (time) that a signal is ON versus the total period of the signal. + Square channel 1 volume: - - - Square Channel 1 Volume: + + Square channel 1 volume - - Square Channel 1 Volume - - - - - - + + + Length of each step in sweep: - - - + + + Length of each step in sweep - - - - The delay between step change + + Square channel 2 volume: - - Wave pattern duty + + Square channel 2 volume - - Square Channel 2 Volume: - - - - - Square Channel 2 Volume + Wave pattern channel volume: - - Wave Channel Volume: + + Wave pattern channel volume - - - Wave Channel Volume + + Noise channel volume: + + + + + Noise channel volume - Noise Channel Volume: + SO1 volume (Right): - - Noise Channel Volume + SO1 volume (Right) - - SO1 Volume (Right): + + SO2 volume (Left): - - SO1 Volume (Right) + + SO2 volume (Left) - - SO2 Volume (Left): - - - - - SO2 Volume (Left) - - - - + Treble: - + Treble - + Bass: - + Bass - - Sweep Direction + + Sweep direction - - - - - - Volume Sweep Direction + + + + + + Volume sweep direction - - Shift Register Width + + Shift register width - - Channel1 to SO1 (Right) + + Channel 1 to SO1 (Right) + + + + + Channel 2 to SO1 (Right) + + + + + Channel 3 to SO1 (Right) - Channel2 to SO1 (Right) + Channel 4 to SO1 (Right) - Channel3 to SO1 (Right) + Channel 1 to SO2 (Left) - - Channel4 to SO1 (Right) + + Channel 2 to SO2 (Left) - - Channel1 to SO2 (Left) + + Channel 3 to SO2 (Left) - Channel2 to SO2 (Left) + Channel 4 to SO2 (Left) - - Channel3 to SO2 (Left) - - - - - Channel4 to SO2 (Left) - - - - - Wave Pattern - - - - - Draw the wave here + + Wave pattern graph FxLine - + Channel send amount - - The FX channel receives input from one or more instrument tracks. - It in turn can be routed to multiple other FX channels. LMMS automatically takes care of preventing infinite loops for you and doesn't allow making a connection that would result in an infinite loop. - -In order to route the channel to another channel, select the FX channel and click on the "send" button on the channel you want to send to. The knob under the send button controls the level of signal that is sent to the channel. - -You can remove and move FX channels in the context menu, which is accessed by right-clicking the FX channel. - - - - - + Move &left - + Move &right - + Rename &channel - + R&emove channel - + Remove &unused channels + + FxLineLcdSpinBox + + + Assign to: + + + + + New FX Channel + + + FxMixer - + Master - - - + + + FX %1 - + Volume - + Mute - + Solo @@ -3211,32 +2981,32 @@ You can remove and move FX channels in the context menu, which is accessed by ri FxMixerView - + FX-Mixer - + FX Fader %1 - + Mute - + Mute this FX channel - + Solo - + Solo FX channel @@ -3244,8 +3014,8 @@ You can remove and move FX channels in the context menu, which is accessed by ri FxRoute - - + + Amount to send from channel %1 to channel %2 @@ -3272,57 +3042,22 @@ You can remove and move FX channels in the context menu, which is accessed by ri GigInstrumentView - Open other GIG file - - - - - Click here to open another GIG file - - - - - Choose the patch - - - - - Click here to change which patch of the GIG file to use - - - - - - Change which instrument of the GIG file is being played - - - - - Which GIG file is currently being used - - - - - Which patch of the GIG file is currently being used - - - - - Gain - - - - - Factor to multiply samples by - - - - + Open GIG file - + + Choose patch + + + + + Gain: + + + + GIG Files (*.gig) @@ -3330,52 +3065,52 @@ You can remove and move FX channels in the context menu, which is accessed by ri GuiApplication - + Working directory - + The LMMS working directory %1 does not exist. Create it now? You can change the directory later via Edit -> Settings. - + Preparing UI - + Preparing song editor - + Preparing mixer - + Preparing controller rack - + Preparing project notes - + Preparing beat/bassline editor - + Preparing piano roll - + Preparing automation editor @@ -3476,139 +3211,104 @@ You can remove and move FX channels in the context menu, which is accessed by ri InstrumentFunctionArpeggioView - + ARPEGGIO - - An arpeggio is a method playing (especially plucked) instruments, which makes the music much livelier. The strings of such instruments (e.g. harps) are plucked like chords. The only difference is that this is done in a sequential order, so the notes are not played at the same time. Typical arpeggios are major or minor triads, but there are a lot of other possible chords, you can select. - - - - + RANGE - + Arpeggio range: - + octave(s) - - Use this knob for setting the arpeggio range in octaves. The selected arpeggio will be played within specified number of octaves. - - - - + CYCLE - + Cycle notes: - + note(s) - - Jumps over n steps in the arpeggio and cycles around if we're over the note range. If the total note range is evenly divisible by the number of steps jumped over you will get stuck in a shorter arpeggio or even on one note. - - - - + SKIP - + Skip rate: - - - + + + % - - The skip function will make the arpeggiator pause one step randomly. From its start in full counter clockwise position and no effect it will gradually progress to full amnesia at maximum setting. - - - - + MISS - + Miss rate: - - The miss function will make the arpeggiator miss the intended note. - - - - + TIME - + Arpeggio time: - + ms - - Use this knob for setting the arpeggio time in milliseconds. The arpeggio time specifies how long each arpeggio-tone should be played. - - - - + GATE - + Arpeggio gate: - - Use this knob for setting the arpeggio gate. The arpeggio gate specifies the percent of a whole arpeggio-tone that should be played. With this you can make cool staccato arpeggios. - - - - + Chord: - + Direction: - + Mode: @@ -4105,92 +3805,87 @@ You can remove and move FX channels in the context menu, which is accessed by ri InstrumentFunctionNoteStackingView - + STACKING - + Chord: - + RANGE - + Chord range: - + octave(s) - - - Use this knob for setting the chord range in octaves. The selected chord will be played within specified number of octaves. - - InstrumentMidiIOView - + ENABLE MIDI INPUT - - + + CHANNEL - - + + VELOCITY - + ENABLE MIDI OUTPUT - + PROGRAM - + NOTE - + MIDI devices to receive MIDI events from - + MIDI devices to send MIDI events to - + CUSTOM BASE VELOCITY - - Specify the velocity normalization base for MIDI-based instruments at 100% note velocity + + Specify the velocity normalization base for MIDI-based instruments at 100% note velocity. - + BASE VELOCITY @@ -4198,13 +3893,13 @@ You can remove and move FX channels in the context menu, which is accessed by ri InstrumentMiscView - + MASTER PITCH - - Enables the use of Master Pitch + + Enables the use of master pitch @@ -4258,22 +3953,22 @@ You can remove and move FX channels in the context menu, which is accessed by ri - LowPass + Low-pass - HiPass + Hi-pass - BandPass csg + Band-pass csg - BandPass czpg + Band-pass czpg @@ -4283,7 +3978,7 @@ You can remove and move FX channels in the context menu, which is accessed by ri - Allpass + All-pass @@ -4293,42 +3988,42 @@ You can remove and move FX channels in the context menu, which is accessed by ri - 2x LowPass + 2x Low-pass - RC LowPass 12dB + RC Low-pass 12 dB/oct - RC BandPass 12dB + RC Band-pass 12 dB/oct - RC HighPass 12dB + RC High-pass 12 dB/oct - RC LowPass 24dB + RC Low-pass 24 dB/oct - RC BandPass 24dB + RC Band-pass 24 dB/oct - RC HighPass 24dB + RC High-pass 24 dB/oct - Vocal Formant Filter + Vocal Formant @@ -4338,17 +4033,17 @@ You can remove and move FX channels in the context menu, which is accessed by ri - SV LowPass + SV Low-pass - SV BandPass + SV Band-pass - SV HighPass + SV High-pass @@ -4375,57 +4070,37 @@ You can remove and move FX channels in the context menu, which is accessed by ri - - These tabs contain envelopes. They're very important for modifying a sound, in that they are almost always necessary for substractive synthesis. For example if you have a volume envelope, you can set when the sound should have a specific volume. If you want to create some soft strings then your sound has to fade in and out very softly. This can be done by setting large attack and release times. It's the same for other envelope targets like panning, cutoff frequency for the used filter and so on. Just monkey around with it! You can really make cool sounds out of a saw-wave with just some envelopes...! - - - - + FILTER - - Here you can select the built-in filter you want to use for this instrument-track. Filters are very important for changing the characteristics of a sound. - - - - + FREQ - - cutoff frequency: + + Cutoff frequency: - + Hz - - Use this knob for setting the cutoff frequency for the selected filter. The cutoff frequency specifies the frequency for cutting the signal by a filter. For example a lowpass-filter cuts all frequencies above the cutoff frequency. A highpass-filter cuts all frequencies below cutoff frequency, and so on... + + Q/RESO - - RESO + + Q/Resonance: - - Resonance: - - - - - Use this knob for setting Q/Resonance for the selected filter. Q/Resonance tells the filter how much it should amplify frequencies near Cutoff-frequency. - - - - + Envelopes, LFOs and filters are not supported by the current instrument. @@ -4433,54 +4108,54 @@ You can remove and move FX channels in the context menu, which is accessed by ri InstrumentTrack - + With this knob you can set the volume of the opened channel. - - + + unnamed_track - + Base note - + Volume - + Panning - + Pitch - + Pitch range - + FX channel - - Master Pitch + + Master pitch - - + + Default preset @@ -4488,52 +4163,52 @@ You can remove and move FX channels in the context menu, which is accessed by ri InstrumentTrackView - + Volume - + Volume: - + VOL - + Panning - + Panning: - + PAN - + MIDI - + Input - + Output - + FX %1: %2 @@ -4541,137 +4216,127 @@ You can remove and move FX channels in the context menu, which is accessed by ri InstrumentTrackWindow - + GENERAL SETTINGS - Use these controls to view and edit the next/previous track in the song editor. + Volume - - Instrument volume - - - - + Volume: - + VOL - + Panning - + Panning: - + PAN - + Pitch - + Pitch: - + cents - + PITCH - + Pitch range (semitones) - + RANGE - + FX channel - + FX - + Save current instrument track settings in a preset file - - Click here, if you want to save current instrument track settings in a preset file. Later you can load this preset by double-clicking it in the preset-browser. - - - - + SAVE - + Envelope, filter & LFO - + Chord stacking & arpeggio - + Effects - - MIDI settings + + MIDI - + Miscellaneous - + Save preset - + XML preset file (*.xpf) - + Plugin @@ -4689,18 +4354,18 @@ You can remove and move FX channels in the context menu, which is accessed by ri - - + + Set value - + Please enter a new value between -96.0 dBFS and 6.0 dBFS: - + Please enter a new value between %1 and %2: @@ -4733,21 +4398,16 @@ You can remove and move FX channels in the context menu, which is accessed by ri Link channels - - - Value: - - - Sorry, no help available. + Value: LadspaEffect - + Unknown LADSPA plugin %1 requested. @@ -4755,12 +4415,12 @@ You can remove and move FX channels in the context menu, which is accessed by ri LcdSpinBox - + Set value - + Please enter a new value between %1 and %2: @@ -4838,136 +4498,126 @@ You can remove and move FX channels in the context menu, which is accessed by ri - - LFO Controller - - - - + BASE - - Base amount: + + Base: - todo + FREQ - - SPD + + LFO frequency: - - LFO-speed: - - - - - Use this knob for setting speed of the LFO. The bigger this value the faster the LFO oscillates and the faster the effect. - - - - + AMNT - + Modulation amount: - - Use this knob for setting modulation amount of the LFO. The bigger this value, the more the connected control (e.g. volume or cutoff-frequency) will be influenced by the LFO. - - - - + PHS - + Phase offset: - - degrees + + degrees - - With this knob you can set the phase offset of the LFO. That means you can move the point within an oscillation where the oscillator begins to oscillate. For example if you have a sine-wave and have a phase-offset of 180 degrees the wave will first go down. It's the same with a square-wave. + + Sine wave - - Click here for a sine-wave. + + Triangle wave - - Click here for a triangle-wave. + + Saw wave - - Click here for a saw-wave. + + Square wave - - Click here for a square-wave. + + Moog saw wave - - Click here for a moog saw-wave. + + Exponential wave - - Click here for an exponential wave. + + White noise - - Click here for white-noise. - - - - - Click here for a user-defined shape. + + User-defined shape. Double click to pick a file. + + + Mutliply modulation frequency by 1 + + + + + Mutliply modulation frequency by 100 + + + + + Divide modulation frequency by 100 + + LmmsCore - + Generating wavetables - + Initializing data structures - + Opening audio and midi devices - + Launching mixer threads @@ -4975,545 +4625,483 @@ Double click to pick a file. MainWindow - + Configuration file - + Error while parsing configuration file at line %1:%2: %3 - + Could not open file - + Could not open file %1 for writing. Please make sure you have write permission to the file and the directory containing the file and try again! - + Project recovery - + There is a recovery file present. It looks like the last session did not end properly or another instance of LMMS is already running. Do you want to recover the project of this session? - - - + + Recover - + Recover the file. Please don't run multiple instances of LMMS when you do this. - - + Discard - + Launch a default session and delete the restored files. This is not reversible. - + Version %1 - + Preparing plugin browser - + Preparing file browsers - + My Projects - + My Samples - + My Presets - + My Home - + Root directory - + Volumes - + My Computer - + Loading background artwork - + &File - + &New - + New from template - + &Open... - + &Recently Opened Projects - + &Save - + Save &As... - + Save as New &Version - + Save as default template - + Import... - + E&xport... - + E&xport Tracks... - + Export &MIDI... - + &Quit - + &Edit - + Undo - + Redo - + Settings - + &View - + &Tools - + &Help - + Online Help - + Help - - What's This? - - - - + About - + Create new project - + Create new project from template - + Open existing project - + Recently opened projects - + Save current project - + Export current project - - What's this? + + Metronome - - Toggle metronome + + + Song Editor - - Show/hide Song-Editor + + + Beat+Bassline Editor - - By pressing this button, you can show or hide the Song-Editor. With the help of the Song-Editor you can edit song-playlist and specify when which track should be played. You can also insert and move samples (e.g. rap samples) directly into the playlist. + + + Piano Roll - - Show/hide Beat+Bassline Editor + + + Automation Editor - - By pressing this button, you can show or hide the Beat+Bassline Editor. The Beat+Bassline Editor is needed for creating beats, and for opening, adding, and removing channels, and for cutting, copying and pasting beat and bassline-patterns, and for other things like that. + + + FX Mixer - - Show/hide Piano-Roll - - - - - Click here to show or hide the Piano-Roll. With the help of the Piano-Roll you can edit melodies in an easy way. - - - - - Show/hide Automation Editor - - - - - Click here to show or hide the Automation Editor. With the help of the Automation Editor you can edit dynamic values in an easy way. - - - - - Show/hide FX Mixer - - - - - Click here to show or hide the FX Mixer. The FX Mixer is a very powerful tool for managing effects for your song. You can insert effects into different effect-channels. - - - - - Show/hide project notes - - - - - Click here to show or hide the project notes window. In this window you can put down your project notes. - - - - + Show/hide controller rack - + + Show/hide project notes + + + + Untitled - + Recover session. Please save your work! - + LMMS %1 - + Recovered project not saved - + This project was recovered from the previous session. It is currently unsaved and will be lost if you don't save it. Do you want to save it now? - + Project not saved - + The current project was modified since last saving. Do you want to save it now? - + Open Project - + LMMS (*.mmp *.mmpz) - + Save Project - + LMMS Project - + LMMS Project Template - + Save project template - + Overwrite default template? - + This will overwrite your current default template. - + Help not available - + Currently there's no help available in LMMS. Please visit http://lmms.sf.net/wiki for documentation on LMMS. - - Song Editor - - - - - Beat+Bassline Editor - - - - - Piano Roll - - - - - Automation Editor - - - - - FX Mixer - - - - - Project Notes - - - - + Controller Rack - + + Project Notes + + + + Volume as dBFS - + Smooth scroll - + Enable note labels in piano roll - + MIDI File (*.mid) - - + + untitled + - Select file for project-export... - + Select directory for writing exported tracks... - + Save project - + Project saved - + The project %1 is now saved. - + Project NOT saved. - + The project %1 was not saved! - + Import file - + MIDI sequences - + Hydrogen projects - + All file types @@ -5521,19 +5109,29 @@ Please visit http://lmms.sf.net/wiki for documentation on LMMS. MeterDialog - - + + Meter Numerator - - + + Meter numerator + + + + + Meter Denominator + Meter denominator + + + + TIME SIG @@ -5567,23 +5165,23 @@ Please visit http://lmms.sf.net/wiki for documentation on LMMS. MidiImport - - + + Setup incomplete - - You do not have set up a default soundfont in the settings dialog (Edit->Settings). Therefore no sound will be played back after importing this MIDI file. You should download a General MIDI soundfont, specify it in settings dialog and try again. + + You have not set up a default soundfont in the settings dialog (Edit->Settings). Therefore no sound will be played back after importing this MIDI file. You should download a General MIDI soundfont, specify it in settings dialog and try again. - + You did not compile LMMS with support for SoundFont2 player, which is used to add default sound to imported MIDI files. Therefore no sound will be played back after importing this MIDI file. - + Track @@ -5606,57 +5204,57 @@ Please visit http://lmms.sf.net/wiki for documentation on LMMS. MidiPort - + Input channel - + Output channel - + Input controller - + Output controller - + Fixed input velocity - + Fixed output velocity - + Fixed output note - + Output MIDI program - + Base velocity - + Receive MIDI-events - + Send MIDI-events @@ -5671,596 +5269,596 @@ Please visit http://lmms.sf.net/wiki for documentation on LMMS. MonstroInstrument - - - Osc 1 Volume - - - Osc 1 Panning + Osc 1 volume - Osc 1 Coarse detune + Osc 1 panning - Osc 1 Fine detune left + Osc 1 coarse detune - Osc 1 Fine detune right + Osc 1 fine detune left - Osc 1 Stereo phase offset + Osc 1 fine detune right - Osc 1 Pulse width + Osc 1 stereo phase offset - Osc 1 Sync send on rise + Osc 1 pulse width - Osc 1 Sync send on fall + Osc 1 sync send on rise - - Osc 2 Volume + + Osc 1 sync send on fall - Osc 2 Panning + Osc 2 volume - Osc 2 Coarse detune + Osc 2 panning - Osc 2 Fine detune left + Osc 2 coarse detune - Osc 2 Fine detune right + Osc 2 fine detune left - Osc 2 Stereo phase offset + Osc 2 fine detune right - Osc 2 Waveform + Osc 2 stereo phase offset - Osc 2 Sync Hard + Osc 2 waveform - Osc 2 Sync Reverse + Osc 2 sync hard - - Osc 3 Volume + + Osc 2 sync reverse - Osc 3 Panning + Osc 3 volume - Osc 3 Coarse detune + Osc 3 panning - Osc 3 Stereo phase offset + Osc 3 coarse detune - Osc 3 Sub-oscillator mix + Osc 3 Stereo phase offset - Osc 3 Waveform 1 + Osc 3 sub-oscillator mix - Osc 3 Waveform 2 + Osc 3 waveform 1 - Osc 3 Sync Hard + Osc 3 waveform 2 - Osc 3 Sync Reverse + Osc 3 sync hard - - LFO 1 Waveform + + Osc 3 Sync reverse - LFO 1 Attack + LFO 1 waveform - LFO 1 Rate + LFO 1 attack - LFO 1 Phase + LFO 1 rate - - LFO 2 Waveform + + LFO 1 phase - LFO 2 Attack + LFO 2 waveform - LFO 2 Rate + LFO 2 attack - LFO 2 Phase + LFO 2 rate - - Env 1 Pre-delay + + LFO 2 phase - Env 1 Attack + Env 1 pre-delay - Env 1 Hold + Env 1 attack - Env 1 Decay + Env 1 hold - Env 1 Sustain + Env 1 decay - Env 1 Release + Env 1 sustain - Env 1 Slope + Env 1 release - - Env 2 Pre-delay + + Env 1 slope - Env 2 Attack + Env 2 pre-delay - Env 2 Hold + Env 2 attack - Env 2 Decay + Env 2 hold - Env 2 Sustain + Env 2 decay - Env 2 Release + Env 2 sustain - Env 2 Slope + Env 2 release - - Osc2-3 modulation + + Env 2 slope - + + Osc 2+3 modulation + + + + Selected view - - - Vol1-Env1 - - - Vol1-Env2 + Osc 1 - Vol env 1 - Vol1-LFO1 + Osc 1 - Vol env 2 - Vol1-LFO2 + Osc 1 - Vol LFO 1 - - Vol2-Env1 + + Osc 1 - Vol LFO 2 - Vol2-Env2 + Osc 2 - Vol env 1 - Vol2-LFO1 + Osc 2 - Vol env 2 - Vol2-LFO2 + Osc 2 - Vol LFO 1 - - Vol3-Env1 + + Osc 2 - Vol LFO 2 - Vol3-Env2 + Osc 3 - Vol env 1 - Vol3-LFO1 + Osc 3 - Vol env 2 - Vol3-LFO2 + Osc 3 - Vol LFO 1 - - Phs1-Env1 + + Osc 3 - Vol LFO 2 - Phs1-Env2 + Osc 1 - Phs env 1 - Phs1-LFO1 + Osc 1 - Phs env 2 - Phs1-LFO2 + Osc 1 - Phs LFO 1 - - Phs2-Env1 + + Osc 1 - Phs LFO 2 - Phs2-Env2 + Osc 2 - Phs env 1 - Phs2-LFO1 + Osc 2 - Phs env 2 - Phs2-LFO2 + Osc 2 - Phs LFO 1 - - Phs3-Env1 + + Osc 2 - Phs LFO 2 - Phs3-Env2 + Osc 3 - Phs env 1 - Phs3-LFO1 + Osc 3 - Phs env 2 - Phs3-LFO2 + Osc 3 - Phs LFO 1 - - Pit1-Env1 + + Osc 3 - Phs LFO 2 - Pit1-Env2 + Osc 1 - Pit env 1 - Pit1-LFO1 + Osc 1 - Pit env 2 - Pit1-LFO2 + Osc 1 - Pit LFO 1 - - Pit2-Env1 + + Osc 1 - Pit LFO 2 - Pit2-Env2 + Osc 2 - Pit env 1 - Pit2-LFO1 + Osc 2 - Pit env 2 - Pit2-LFO2 + Osc 2 - Pit LFO 1 - - Pit3-Env1 + + Osc 2 - Pit LFO 2 - Pit3-Env2 + Osc 3 - Pit env 1 - Pit3-LFO1 + Osc 3 - Pit env 2 - Pit3-LFO2 + Osc 3 - Pit LFO 1 - - PW1-Env1 + + Osc 3 - Pit LFO 2 - PW1-Env2 + Osc 1 - PW env 1 - PW1-LFO1 + Osc 1 - PW env 2 - PW1-LFO2 + Osc 1 - PW LFO 1 - - Sub3-Env1 + + Osc 1 - PW LFO 2 - Sub3-Env2 + Osc 3 - Sub env 1 - Sub3-LFO1 + Osc 3 - Sub env 2 - Sub3-LFO2 + Osc 3 - Sub LFO 1 - - - Sine wave - - - - - Bandlimited Triangle wave - - - - - Bandlimited Saw wave - - - - - Bandlimited Ramp wave + + Osc 3 - Sub LFO 2 - Bandlimited Square wave + + Sine wave - Bandlimited Moog saw wave + Bandlimited Triangle wave - - Soft square wave + Bandlimited Saw wave - Absolute sine wave + Bandlimited Ramp wave - - Exponential wave + Bandlimited Square wave - White noise + Bandlimited Moog saw wave - Digital Triangle wave + + Soft square wave - Digital Saw wave + Absolute sine wave - Digital Ramp wave + + Exponential wave - Digital Square wave + White noise + Digital Triangle wave + + + + + Digital Saw wave + + + + + Digital Ramp wave + + + + + Digital Square wave + + + + Digital Moog saw wave - + Triangle wave - + Saw wave - + Ramp wave - + Square wave - + Moog saw wave - + Abs. sine wave - + Random - + Random smooth @@ -6268,433 +5866,240 @@ Please visit http://lmms.sf.net/wiki for documentation on LMMS. MonstroView - + Operators view - - The Operators view contains all the operators. These include both audible operators (oscillators) and inaudible operators, or modulators: Low-frequency oscillators and Envelopes. - -Knobs and other widgets in the Operators view have their own what's this -texts, so you can get more specific help for them that way. - - - - + Matrix view - - The Matrix view contains the modulation matrix. Here you can define the modulation relationships between the various operators: Each audible operator (oscillators 1-3) has 3-4 properties that can be modulated by any of the modulators. Using more modulations consumes more CPU power. - -The view is divided to modulation targets, grouped by the target oscillator. Available targets are volume, pitch, phase, pulse width and sub-osc ratio. Note: some targets are specific to one oscillator only. - -Each modulation target has 4 knobs, one for each modulator. By default the knobs are at 0, which means no modulation. Turning a knob to 1 causes that modulator to affect the modulation target as much as possible. Turning it to -1 does the same, but the modulation is inversed. - - - - + + - Volume - + + - Panning - + + - Coarse detune - + + - semitones - - - Finetune left + + + Fine tune left - - - - + + + + cents - - - Finetune right + + + Fine tune right - - - + + + Stereo phase offset - - - - - + + + + + deg - + Pulse width - + Send sync on pulse rise - + Send sync on pulse fall - + Hard sync oscillator 2 - + Reverse sync oscillator 2 - + Sub-osc mix - + Hard sync oscillator 3 - + Reverse sync oscillator 3 + + + + + + Attack + + + + + + Rate + + + + + + Phase + + + + + + Pre-delay + + + + + + Hold + + + + + + Decay + + - - - Attack + Sustain - Rate + Release - Phase - - - - - - Pre-delay - - - - - - Hold - - - - - - Decay - - - - - - Sustain - - - - - - Release - - - - - Slope - - Mix Osc2 with Osc3 + + Mix osc 2 with osc 3 - - Modulate amplitude of Osc3 with Osc2 + + Modulate amplitude of osc 3 by osc 2 - - Modulate frequency of Osc3 with Osc2 + + Modulate frequency of osc 3 by osc 2 - - Modulate phase of Osc3 with Osc2 + + Modulate phase of osc 3 by osc 2 + + + + + + + + + - The CRS knob changes the tuning of oscillator 1 in semitone steps. - - - - The CRS knob changes the tuning of oscillator 2 in semitone steps. - - - - The CRS knob changes the tuning of oscillator 3 in semitone steps. - - - - + + + + + - FTL and FTR change the finetuning of the oscillator for left and right channels respectively. These can add stereo-detuning to the oscillator which widens the stereo image and causes an illusion of space. - - - + + - The SPO knob modifies the difference in phase between left and right channels. Higher difference creates a wider stereo image. - - - + - The PW knob controls the pulse width, also known as duty cycle, of oscillator 1. Oscillator 1 is a digital pulse wave oscillator, it doesn't produce bandlimited output, which means that you can use it as an audible oscillator but it will cause aliasing. You can also use it as an inaudible source of a sync signal, which can be used to synchronize oscillators 2 and 3. - - - + + + + - Send Sync on Rise: When enabled, the Sync signal is sent every time the state of oscillator 1 changes from low to high, ie. when the amplitude changes from -1 to 1. Oscillator 1's pitch, phase and pulse width may affect the timing of syncs, but its volume has no effect on them. Sync signals are sent independently for both left and right channels. - - - - - Send Sync on Fall: When enabled, the Sync signal is sent every time the state of oscillator 1 changes from high to low, ie. when the amplitude changes from 1 to -1. Oscillator 1's pitch, phase and pulse width may affect the timing of syncs, but its volume has no effect on them. Sync signals are sent independently for both left and right channels. - - - + + + + + + + + + - Hard sync: Every time the oscillator receives a sync signal from oscillator 1, its phase is reset to 0 + whatever its phase offset is. - - - - - - Reverse sync: Every time the oscillator receives a sync signal from oscillator 1, the amplitude of the oscillator gets inverted. - - - - - Choose waveform for oscillator 2. - - - - - Choose waveform for oscillator 3's first sub-osc. Oscillator 3 can smoothly interpolate between two different waveforms. - - - - - Choose waveform for oscillator 3's second sub-osc. Oscillator 3 can smoothly interpolate between two different waveforms. - - - - - The SUB knob changes the mixing ratio of the two sub-oscs of oscillator 3. Each sub-osc can be set to produce a different waveform, and oscillator 3 can smoothly interpolate between them. All incoming modulations to oscillator 3 are applied to both sub-oscs/waveforms in the exact same way. - - - - - In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. - -Mix mode means no modulation: the outputs of the oscillators are simply mixed together. - - - - - In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. - -AM means amplitude modulation: Oscillator 3's amplitude (volume) is modulated by oscillator 2. - - - - - In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. - -FM means frequency modulation: Oscillator 3's frequency (pitch) is modulated by oscillator 2. The frequency modulation is implemented as phase modulation, which gives a more stable overall pitch than "pure" frequency modulation. - - - - - In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. - -PM means phase modulation: Oscillator 3's phase is modulated by oscillator 2. It differs from frequency modulation in that the phase changes are not cumulative. - - - - - Select the waveform for LFO 1. -"Random" and "Random smooth" are special waveforms: they produce random output, where the rate of the LFO controls how often the state of the LFO changes. The smooth version interpolates between these states with cosine interpolation. These random modes can be used to give "life" to your presets - add some of that analog unpredictability... - - - - - Select the waveform for LFO 2. -"Random" and "Random smooth" are special waveforms: they produce random output, where the rate of the LFO controls how often the state of the LFO changes. The smooth version interpolates between these states with cosine interpolation. These random modes can be used to give "life" to your presets - add some of that analog unpredictability... - - - - - - Attack causes the LFO to come on gradually from the start of the note. - - - - - - Rate sets the speed of the LFO, measured in milliseconds per cycle. Can be synced to tempo. - - - - - - PHS controls the phase offset of the LFO. - - - - - - PRE, or pre-delay, delays the start of the envelope from the start of the note. 0 means no delay. - - - - - - ATT, or attack, controls how fast the envelope ramps up at start, measured in milliseconds. A value of 0 means instant. - - - - - - HOLD controls how long the envelope stays at peak after the attack phase. - - - - - - DEC, or decay, controls how fast the envelope falls off from its peak, measured in milliseconds it would take to go from peak to zero. The actual decay may be shorter if sustain is used. - - - - - - SUS, or sustain, controls the sustain level of the envelope. The decay phase will not go below this level as long as the note is held. - - - - - - REL, or release, controls how long the release is for the note, measured in how long it would take to fall from peak to zero. Actual release may be shorter, depending on at what phase the note is released. - - - - - - The slope knob controls the curve or shape of the envelope. A value of 0 creates straight rises and falls. Negative values create curves that start slowly, peak quickly and fall of slowly again. Positive values create curves that start and end quickly, and stay longer near the peaks. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + Modulation amount @@ -6718,7 +6123,7 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator - Dry Gain: + Dry gain: @@ -6728,7 +6133,7 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator - Lowpass stages: + Low-pass stages: @@ -6738,7 +6143,7 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator - Swap left and right input channel for reflections + Swap left and right input channels for reflections @@ -6746,32 +6151,32 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator NesInstrument - Channel 1 Coarse detune + Channel 1 coarse detune - Channel 1 Volume + Channel 1 volume - Channel 1 Envelope length + Channel 1 envelope length - Channel 1 Duty cycle + Channel 1 duty cycle - Channel 1 Sweep amount + Channel 1 sweep amount - Channel 1 Sweep rate + Channel 1 sweep rate @@ -6786,52 +6191,52 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator - Channel 2 Envelope length + Channel 2 envelope length - Channel 2 Duty cycle + Channel 2 duty cycle - Channel 2 Sweep amount + Channel 2 sweep amount - Channel 2 Sweep rate + Channel 2 sweep rate - Channel 3 Coarse detune + Channel 3 coarse detune - Channel 3 Volume + Channel 3 volume - Channel 4 Volume + Channel 4 volume - Channel 4 Envelope length + Channel 4 envelope length - Channel 4 Noise frequency + Channel 4 noise frequency - Channel 4 Noise frequency sweep + Channel 4 noise frequency sweep @@ -6992,7 +6397,7 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator - Master Volume + Master volume @@ -7004,174 +6409,174 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator OpulenzInstrument - + Patch - - - Op 1 Attack - - - - - Op 1 Decay - - - Op 1 Sustain + Op 1 attack - Op 1 Release + Op 1 decay - Op 1 Level + Op 1 sustain - Op 1 Level Scaling + Op 1 release - Op 1 Frequency Multiple + Op 1 level - Op 1 Feedback + Op 1 level scaling - Op 1 Key Scaling Rate + Op 1 frequency multiplier - Op 1 Percussive Envelope + Op 1 feedback - Op 1 Tremolo + Op 1 key scaling rate - Op 1 Vibrato + Op 1 percussive envelope - - Op 1 Waveform + + Op 1 tremolo - - Op 2 Attack + + Op 1 vibrato - - Op 2 Decay + + Op 1 waveform - Op 2 Sustain + Op 2 attack - Op 2 Release + Op 2 decay - Op 2 Level + Op 2 sustain - Op 2 Level Scaling + Op 2 release - Op 2 Frequency Multiple + Op 2 level - Op 2 Key Scaling Rate + Op 2 level scaling - Op 2 Percussive Envelope + Op 2 frequency multiplier - Op 2 Tremolo + Op 2 key scaling rate - Op 2 Vibrato + Op 2 percussive envelope - - Op 2 Waveform + + Op 2 tremolo + + + + + Op 2 vibrato - FM - - - - - Vibrato Depth + Op 2 waveform - Tremolo Depth + FM + + + + + Vibrato depth + + + + + Tremolo depth OpulenzInstrumentView - + Attack - + Decay - + Release - + Frequency multiplier @@ -7179,29 +6584,29 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator OscillatorObject - + Osc %1 waveform - + Osc %1 harmonic - + Osc %1 volume - + Osc %1 panning - + Osc %1 fine detuning left @@ -7283,57 +6688,42 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator PatmanView - - Open other patch + + Open patch - - Click here to open another patch-file. Loop and Tune settings are not reset. - - - - + Loop - + Loop mode - - Here you can toggle the Loop mode. If enabled, PatMan will use the loop information available in the file. - - - - + Tune - + Tune mode - - Here you can toggle the Tune mode. If enabled, PatMan will tune the sample to match the note's frequency. - - - - + No file selected - + Open patch file - + Patch-Files (*.pat) @@ -7341,37 +6731,42 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator PatternView - + Open in piano-roll - + + Set as ghost in piano-roll + + + + Clear all notes - + Reset name - + Change name - + Add steps - + Remove steps - + Clone Steps @@ -7379,17 +6774,17 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator PeakController - + Peak Controller - + Peak Controller Bug - + Due to a bug in older version of LMMS, the peak controllers may not be connect properly. Please ensure that peak controllers are connected properly and re-save this file. Sorry for any inconvenience caused. @@ -7416,7 +6811,7 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator - Base amount: + Base: @@ -7436,7 +6831,7 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator - Amount Multiplicator: + Amount multiplicator: @@ -7469,140 +6864,150 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator Treshold: - - - PeakControllerEffectControls - - Base value - - - - - Modulation amount - - - - - Attack - - - - - Release - - - - - Treshold - - - - + Mute output - - Abs Value + + Absolute value + + + + + PeakControllerEffectControls + + + Base value - - Amount Multiplicator + + Modulation amount + + + + + Attack + + + + + Release + + + + + Treshold + + + + + Mute output + + + + + Absolute value + + + + + Amount multiplicator PianoRoll - + Note Velocity - + Note Panning - + Mark/unmark current semitone - + Mark/unmark all corresponding octave semitones - + Mark current scale - + Mark current chord - + Unmark all - + Select all notes on this key - + Note lock - + Last note - + No scale - + No chord - + Velocity: %1% - + Panning: %1% left - + Panning: %1% right - + Panning: center - + Please open a pattern by double-clicking on it! - - + + Please enter a new value between %1 and %2: @@ -7610,174 +7015,129 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator PianoRollWindow - + Play/pause current pattern (Space) - + Record notes from MIDI-device/channel-piano - + Record notes from MIDI-device/channel-piano while playing song or BB track - + + Record notes from MIDI-device/channel-piano, one step at the time + + + + Stop playing of current pattern (Space) - - Click here to play the current pattern. This is useful while editing it. The pattern is automatically looped when its end is reached. - - - - - Click here to record notes from a MIDI-device or the virtual test-piano of the according channel-window to the current pattern. When recording all notes you play will be written to this pattern and you can play and edit them afterwards. - - - - - Click here to record notes from a MIDI-device or the virtual test-piano of the according channel-window to the current pattern. When recording all notes you play will be written to this pattern and you will hear the song or BB track in the background. - - - - - Click here to stop playback of current pattern. - - - - + Edit actions - + Draw mode (Shift+D) - + Erase mode (Shift+E) - + Select mode (Shift+S) - - Detune mode (Shift+T) + + Pitch Bend mode (Shift+T) - - Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold %1 to temporarily go into select mode. - - - - - Click here and erase mode will be activated. In this mode you can erase notes. You can also press 'Shift+E' on your keyboard to activate this mode. - - - - - Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold %1 in draw mode to temporarily use select mode. - - - - - Click here and detune mode will be activated. In this mode you can click a note to open its automation detuning. You can utilize this to slide notes from one to another. You can also press 'Shift+T' on your keyboard to activate this mode. - - - - + Quantize - + Copy paste controls - - Cut selected notes (%1+X) + + Cut (%1+X) - - Copy selected notes (%1+C) + + Copy (%1+C) - - Paste notes from clipboard (%1+V) + + Paste (%1+V) - - Click here and the selected notes will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. - - - - - Click here and the selected notes will be copied into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. - - - - - Click here and the notes from the clipboard will be pasted at the first visible measure. - - - - + Timeline controls - + Zoom and note controls - - This controls the magnification of an axis. It can be helpful to choose magnification for a specific task. For ordinary editing, the magnification should be fitted to your smallest notes. + + Horizontal zooming - - The 'Q' stands for quantization, and controls the grid size notes and control points snap to. With smaller quantization values, you can draw shorter notes in Piano Roll, and more exact control points in the Automation Editor. + + Quantization - - This lets you select the length of new notes. 'Last Note' means that LMMS will use the note length of the note you last edited + + Note length - - The feature is directly connected to the context-menu on the virtual keyboard, to the left in Piano Roll. After you have chosen the scale you want in this drop-down menu, you can right click on a desired key in the virtual keyboard, and then choose 'Mark current Scale'. LMMS will highlight all notes that belongs to the chosen scale, and in the key you have selected! + + Scale - - Let you select a chord which LMMS then can draw or highlight.You can find the most common chords in this drop-down menu. After you have selected a chord, click anywhere to place the chord, and right click on the virtual keyboard to open context menu and highlight the chord. To return to single note placement, you need to choose 'No chord' in this drop-down menu. + + Chord - - + + Clear ghost notes + + + + + Piano-Roll - %1 - - + + Piano-Roll - no pattern @@ -7785,7 +7145,7 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator PianoView - + Base note @@ -7793,23 +7153,23 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator Plugin - + Plugin not found - + The plugin "%1" wasn't found or could not be loaded! Reason: "%2" - + Error while loading plugin - + Failed to load plugin "%1"! @@ -7817,17 +7177,17 @@ Reason: "%2" PluginBrowser - + Instrument Plugins - + Instrument browser - + Drag an instrument into either the Song-Editor, the Beat+Bassline Editor or into an existing instrument track. @@ -7835,12 +7195,12 @@ Reason: "%2" PluginFactory - + Plugin not found. - + LMMS plugin %1 does not have a plugin descriptor named %2! @@ -7873,122 +7233,122 @@ Reason: "%2" - + &Redo - + %1+Y - + &Copy - + %1+C - + Cu&t - + %1+X - + &Paste - + %1+V - + Format Actions - + &Bold - + %1+B - + &Italic - + %1+I - + &Underline - + %1+U - + &Left - + %1+L - + C&enter - + %1+E - + &Right - + %1+R - + &Justify - + %1+J - + &Color... @@ -7996,22 +7356,22 @@ Reason: "%2" ProjectRenderer - + WAV (*.wav) - + FLAC (*.flac) - + OGG (*.ogg) - + MP3 (*.mp3) @@ -8020,26 +7380,26 @@ Reason: "%2" QWidget - + Name: - + Maker: - + Copyright: - + Requires Real Time: @@ -8047,9 +7407,9 @@ Reason: "%2" - - - + + + Yes @@ -8057,38 +7417,38 @@ Reason: "%2" - - - + + + No - + Real Time Capable: - + In Place Broken: - + Channels In: - + Channels Out: - + File: %1 @@ -8115,7 +7475,7 @@ Reason: "%2" - Input Gain: + Input gain: @@ -8145,7 +7505,7 @@ Reason: "%2" - Output Gain: + Output gain: @@ -8153,7 +7513,7 @@ Reason: "%2" ReverbSCControls - Input Gain + Input gain @@ -8168,74 +7528,322 @@ Reason: "%2" - Output Gain + Output gain + + + + + SaControls + + + Pause + + + + + Reference freeze + + + + + Waterfall + + + + + Averaging + + + + + Stereo + + + + + Peak hold + + + + + Logarithmic frequency + + + + + Logarithmic amplitude + + + + + Frequency range + + + + + Amplitude range + + + + + FFT block size + + + + + FFT window type + + + + + + Full (auto) + + + + + + Audible + + + + + Bass + + + + + Mids + + + + + High + + + + + Extended + + + + + + Default + + + + + Noise + + + + + (High time res.) + + + + + (High freq. res.) + + + + + Rectangular (Off) + + + + + + Blackman-Harris (Default) + + + + + Hamming + + + + + Hanning + + + + + SaControlsDialog + + + Pause + + + + + Pause data acquisition + + + + + Reference freeze + + + + + Freeze current input as a reference / disable falloff in peak-hold mode. + + + + + Waterfall + + + + + Display real-time spectrogram + + + + + Averaging + + + + + Enable exponential moving average + + + + + Stereo + + + + + Display stereo channels separately + + + + + Peak hold + + + + + Display envelope of peak values + + + + + Logarithmic frequency + + + + + Switch between logarithmic and linear frequency scale + + + + + + Frequency range + + + + + Logarithmic amplitude + + + + + Switch between logarithmic and linear amplitude scale + + + + + + Amplitude range + + + + + FFT block bize + + + + + FFT block size + + + + + + FFT window type SampleBuffer - + Fail to open file - + Audio files are limited to %1 MB in size and %2 minutes of playing time - + Open audio file - + All Audio-Files (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw) - + Wave-Files (*.wav) - + OGG-Files (*.ogg) - + DrumSynth-Files (*.ds) - + FLAC-Files (*.flac) - + SPEEX-Files (*.spx) - + VOC-Files (*.voc) - + AIFF-Files (*.aif *.aiff) - + AU-Files (*.au) - + RAW-Files (*.raw) @@ -8243,32 +7851,32 @@ Reason: "%2" SampleTCOView - - double-click to select sample + + Double-click to open sample - + Delete (middle mousebutton) - + Cut - + Copy - + Paste - + Mute/unmute (<%1> + middle click) @@ -8276,18 +7884,23 @@ Reason: "%2" SampleTrack - + Volume - + Panning - - + + FX channel + + + + + Sample track @@ -8295,386 +7908,326 @@ Reason: "%2" SampleTrackView - + Track volume - + Channel volume: - + VOL - + Panning - + Panning: - + PAN + + + FX %1: %2 + + + + + SampleTrackWindow + + + GENERAL SETTINGS + + + + + Sample volume + + + + + Volume: + + + + + VOL + + + + + Panning + + + + + Panning: + + + + + PAN + + + + + FX channel + + + + + FX + + + + + SaveOptionsWidget + + + Discard MIDI connections + + SetupDialog - + Setup LMMS - - + + General settings - + BUFFER SIZE - - - Reset to default-value + + + Reset to default value - + MISC - - Enable tooltips + + Use built-in NaN handler - - Show restart warning after changing settings - - - - - Display volume as dBFS - - - - - Compress project files per default - - - - - One instrument track window mode - - - - - HQ-mode for output audio-device - - - - - Compact track buttons - - - - - Sync VST plugins to host playback - - - - - Enable note labels in piano roll - - - - - Enable waveform display by default - - - - - Keep effects running even without input - - - - - Create backup file when saving a project - - - - - Reopen last project on start - - - - + PLUGIN EMBEDDING - + No embedding - + Embed using Qt API - + Embed using native Win32 API - + Embed using XEmbed protocol - + + Keep plugin windows on top when not embedded + + + + LANGUAGE - - + + Paths - + Directories - - LMMS working directory - - - - - Themes directory - - - - - Background artwork - - - - - VST-plugin directory - - - - - GIG directory - - - - - SF2 directory - - - - - LADSPA plugin directories - - - - - STK rawwave directory - - - - - Default Soundfont File - - - - - + + Performance settings - + Auto save - + Enable auto-save - + Allow auto-save while playing - + UI effects vs. performance - + Smooth scroll in Song Editor - + Show playback cursor in AudioFileProcessor - - + + Audio settings - + AUDIO INTERFACE - - + + MIDI settings - + MIDI INTERFACE - + OK - + Cancel - + Restart LMMS - - Please note that most changes won't take effect until you restart LMMS!<br><br>Do you want to restart now? <b>All your unsaved works will be lost!<b> + + Please note that most changes won't take effect until you restart LMMS! - + Frames: %1 Latency: %2 ms - - Here you can setup the internal buffer-size used by LMMS. Smaller values result in a lower latency but also may cause unusable sound or bad performance, especially on older computers or systems with a non-realtime kernel. - - - - + Choose LMMS working directory - + Choose your GIG directory - + Choose your SF2 directory - + Choose your VST-plugin directory - + Choose artwork-theme directory - + Choose LADSPA plugin directory - + Choose STK rawwave directory - + Choose default SoundFont - + Choose background artwork - + minutes - + minute - + Disabled - + Auto-save interval: %1 - - - Set the time between automatic backup to %1. -Remember to also save your project manually. You can choose to disable saving while playing, something some older systems find difficult. - - - - - Here you can select your preferred audio-interface. Depending on the configuration of your system during compilation time you can choose between ALSA, JACK, OSS and more. Below you see a box which offers controls to setup the selected audio-interface. - - - - - Here you can select your preferred MIDI-interface. Depending on the configuration of your system during compilation time you can choose between ALSA, OSS and more. Below you see a box which offers controls to setup the selected MIDI-interface. - - Song @@ -8694,12 +8247,12 @@ Remember to also save your project manually. You can choose to disable saving wh - + LMMS Error report - + The following errors occured while loading: @@ -8707,53 +8260,53 @@ Remember to also save your project manually. You can choose to disable saving wh SongEditor - + Could not open file - + Could not open file %1. You probably have no permissions to read this file. Please make sure to have at least read permissions to the file and try again. - + Could not write file - + Could not open %1 for writing. You probably are not permitted to write to this file. Please make sure you have write-access to the file and try again. - + Error in file - + The file %1 seems to contain errors and therefore can't be loaded. - + Version difference - + This %1 was created with LMMS %2. - + template - + project @@ -8764,53 +8317,40 @@ Remember to also save your project manually. You can choose to disable saving wh - TEMPO/BPM + TEMPO - tempo of song + Tempo in BPM - - The tempo of a song is specified in beats per minute (BPM). If you want to change the tempo of your song, change this value. Every measure has four beats, so the tempo in BPM specifies, how many measures / 4 should be played within a minute (or how many measures should be played within four minutes). - - - - + High quality mode - - + + + Master volume - - master volume - - - - - + + + Master pitch - - master pitch - - - - + Value: %1% - + Value: %1 semitones @@ -8818,131 +8358,108 @@ Remember to also save your project manually. You can choose to disable saving wh SongEditorWindow - + Song-Editor - + Play song (Space) - + Record samples from Audio-device - + Record samples from Audio-device while playing song or BB track - + Stop song (Space) - - Click here, if you want to play your whole song. Playing will be started at the song-position-marker (green). You can also move it while playing. - - - - - Click here, if you want to stop playing of your song. The song-position-marker will be set to the start of your song. - - - - + Track actions - + Add beat/bassline - + Add sample-track - + Add automation-track - + Edit actions - + Draw mode - + Edit mode (select and move) - + Timeline controls - + Zoom controls - - - SpectrumAnalyzerControlDialog - - Linear spectrum - - - - - Linear Y axis + + Horizontal zooming - SpectrumAnalyzerControls + StepRecorderWidget - - Linear spectrum + + Hint - - Linear Y axis - - - - - Channel mode + + Move recording curser using <Left/Right> arrows SubWindow - + Close - + Maximize - + Restore @@ -8960,7 +8477,7 @@ Remember to also save your project manually. You can choose to disable saving wh TempoSyncKnob - + Tempo Sync @@ -9010,42 +8527,42 @@ Remember to also save your project manually. You can choose to disable saving wh - + Custom - + Synced to Eight Beats - + Synced to Whole Note - + Synced to Half Note - + Synced to Quarter Note - + Synced to 8th Note - + Synced to 16th Note - + Synced to 32nd Note @@ -9054,36 +8571,36 @@ Remember to also save your project manually. You can choose to disable saving wh TimeDisplayWidget - click to change time units + Time units - + MIN - + SEC - + MSEC - + BAR - + BEAT - + TICK @@ -9091,43 +8608,43 @@ Remember to also save your project manually. You can choose to disable saving wh TimeLineWidget - - Enable/disable auto-scrolling + + Auto scrolling - - Enable/disable loop-points + + Loop points - + After stopping go back to begin - + After stopping go back to position at which playing was started - + After stopping keep position - - + + Hint - + Press <%1> to disable magnetic loop points. - + Hold <Shift> to move the begin loop point; Press <%1> to disable magnetic loop points. @@ -9135,12 +8652,12 @@ Remember to also save your project manually. You can choose to disable saving wh Track - + Mute - + Solo @@ -9176,13 +8693,13 @@ Please make sure you have read-permission to the file and the directory containi - + Cancel - + Please wait... @@ -9202,7 +8719,7 @@ Please make sure you have read-permission to the file and the directory containi - + Importing MIDI-file... @@ -9210,7 +8727,7 @@ Please make sure you have read-permission to the file and the directory containi TrackContentObject - + Mute @@ -9218,58 +8735,58 @@ Please make sure you have read-permission to the file and the directory containi TrackContentObjectView - - - Current length - - - - + Current position + + + Current length + + - Press <%1> and drag to make a copy. - - - - - Press <%1> for free resizing. - - - - - Hint - - - - + %1:%2 (%3:%4 to %5:%6) - + + Press <%1> and drag to make a copy. + + + + + Press <%1> for free resizing. + + + + + Hint + + + + Delete (middle mousebutton) - + Cut - + Copy - + Paste - + Mute/unmute (<%1> + middle click) @@ -9277,17 +8794,18 @@ Please make sure you have read-permission to the file and the directory containi TrackOperationsWidget - - Press <%1> while clicking on move-grip to begin a new drag'n'drop-action. + + Press <%1> while clicking on move-grip to begin a new drag'n'drop action. - Actions for this track + Actions + Mute @@ -9297,11 +8815,6 @@ Please make sure you have read-permission to the file and the directory containi Solo - - - Mute this track - - Clone this track @@ -9318,22 +8831,22 @@ Please make sure you have read-permission to the file and the directory containi - + FX %1: %2 - + Assign to new FX Channel - + Turn all recording on - + Turn all recording off @@ -9342,196 +8855,166 @@ Please make sure you have read-permission to the file and the directory containi TripleOscillatorView - Use phase modulation for modulating oscillator 1 with oscillator 2 + Modulate phase of oscillator 1 by oscillator 2 - - Use amplitude modulation for modulating oscillator 1 with oscillator 2 + + Modulate amplitude of oscillator 1 by oscillator 2 - - Mix output of oscillator 1 & 2 + + Mix output of oscillators 1 & 2 - + Synchronize oscillator 1 with oscillator 2 - - Use frequency modulation for modulating oscillator 1 with oscillator 2 + + Modulate frequency of oscillator 1 by oscillator 2 - - Use phase modulation for modulating oscillator 2 with oscillator 3 + + Modulate phase of oscillator 2 by oscillator 3 + + + + + Modulate amplitude of oscillator 2 by oscillator 3 - Use amplitude modulation for modulating oscillator 2 with oscillator 3 + Mix output of oscillators 2 & 3 - - Mix output of oscillator 2 & 3 - - - - + Synchronize oscillator 2 with oscillator 3 - - Use frequency modulation for modulating oscillator 2 with oscillator 3 + + Modulate frequency of oscillator 2 by oscillator 3 - + Osc %1 volume: - - With this knob you can set the volume of oscillator %1. When setting a value of 0 the oscillator is turned off. Otherwise you can hear the oscillator as loud as you set it here. - - - - + Osc %1 panning: - - With this knob you can set the panning of the oscillator %1. A value of -100 means 100% left and a value of 100 moves oscillator-output right. - - - - + Osc %1 coarse detuning: - + semitones - - With this knob you can set the coarse detuning of oscillator %1. You can detune the oscillator 24 semitones (2 octaves) up and down. This is useful for creating sounds with a chord. - - - - + Osc %1 fine detuning left: - - + + cents - - With this knob you can set the fine detuning of oscillator %1 for the left channel. The fine-detuning is ranged between -100 cents and +100 cents. This is useful for creating "fat" sounds. - - - - + Osc %1 fine detuning right: - - With this knob you can set the fine detuning of oscillator %1 for the right channel. The fine-detuning is ranged between -100 cents and +100 cents. This is useful for creating "fat" sounds. - - - - + Osc %1 phase-offset: - - + + degrees - - With this knob you can set the phase-offset of oscillator %1. That means you can move the point within an oscillation where the oscillator begins to oscillate. For example if you have a sine-wave and have a phase-offset of 180 degrees the wave will first go down. It's the same with a square-wave. - - - - + Osc %1 stereo phase-detuning: - - With this knob you can set the stereo phase-detuning of oscillator %1. The stereo phase-detuning specifies the size of the difference between the phase-offset of left and right channel. This is very good for creating wide stereo sounds. + + Sine wave - - Use a sine-wave for current oscillator. + + Triangle wave - - Use a triangle-wave for current oscillator. + + Saw wave - - Use a saw-wave for current oscillator. + + Square wave - - Use a square-wave for current oscillator. + + Moog-like saw wave - - Use a moog-like saw-wave for current oscillator. + + Exponential wave - - Use an exponential wave for current oscillator. + + White noise - - Use white-noise for current oscillator. - - - - - Use a user-defined waveform for current oscillator. + + User-defined wave VersionedSaveDialog - + Increment version number - + Decrement version number - + + Save Options + + + + already exists. Do you want to replace it? @@ -9539,113 +9022,73 @@ Please make sure you have read-permission to the file and the directory containi VestigeInstrumentView - - Open other VST-plugin + + + Open VST plugin - - Click here, if you want to open another VST-plugin. After clicking on this button, a file-open-dialog appears and you can select your file. + + Control VST plugin from LMMS host - - Control VST-plugin from LMMS host + + Open VST plugin preset - - Click here, if you want to control VST-plugin from host. - - - - - Open VST-plugin preset - - - - - Click here, if you want to open another *.fxp, *.fxb VST-plugin preset. - - - - + Previous (-) - - - Click here, if you want to switch to another VST-plugin preset program. - - - - + Save preset - - Click here, if you want to save current VST-plugin preset program. - - - - + Next (+) - - Click here to select presets that are currently loaded in VST. - - - - + Show/hide GUI - - Click here to show or hide the graphical user interface (GUI) of your VST-plugin. - - - - + Turn off all notes - - Open VST-plugin - - - - + DLL-files (*.dll) - + EXE-files (*.exe) - - No VST-plugin loaded + + No VST plugin loaded - + Preset - + by - + - VST plugin control @@ -9653,12 +9096,12 @@ Please make sure you have read-permission to the file and the directory containi VisualizationWidget - - click to enable/disable visualization of master-output + + Oscilloscope - + Click to enable @@ -9666,69 +9109,43 @@ Please make sure you have read-permission to the file and the directory containi VstEffectControlDialog - + Show/hide - - Control VST-plugin from LMMS host + + Control VST plugin from LMMS host - - Click here, if you want to control VST-plugin from host. + + Open VST plugin preset - - Open VST-plugin preset - - - - - Click here, if you want to open another *.fxp, *.fxb VST-plugin preset. - - - - + Previous (-) - - - Click here, if you want to switch to another VST-plugin preset program. - - - - + Next (+) - - Click here to select presets that are currently loaded in VST. - - - - + Save preset - - Click here, if you want to save current VST-plugin preset program. - - - - - + + Effect by: - + &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /> @@ -9736,69 +9153,69 @@ Please make sure you have read-permission to the file and the directory containi VstPlugin - - + + The VST plugin %1 could not be loaded. - + Open Preset - - + + Vst Plugin Preset (*.fxp *.fxb) - + : default - + " - + ' - + Save Preset - + .fxp - + .FXP - + .FXB - + .fxb - + Loading plugin - + Please wait while loading VST plugin... @@ -10062,17 +9479,17 @@ Please make sure you have read-permission to the file and the directory containi - Modulate amplitude of A1 with output of A2 + Modulate amplitude of A1 by output of A2 - Ring-modulate A1 and A2 + Ring modulate A1 and A2 - Modulate phase of A1 with output of A2 + Modulate phase of A1 by output of A2 @@ -10082,17 +9499,17 @@ Please make sure you have read-permission to the file and the directory containi - Modulate amplitude of B1 with output of B2 + Modulate amplitude of B1 by output of B2 - Ring-modulate B1 and B2 + Ring modulate B1 and B2 - Modulate phase of B1 with output of B2 + Modulate phase of B1 by output of B2 @@ -10110,7 +9527,7 @@ Please make sure you have read-permission to the file and the directory containi - Click to load a waveform from a sample file + Load a waveform from a sample file @@ -10120,7 +9537,7 @@ Please make sure you have read-permission to the file and the directory containi - Click to shift phase by -15 degrees + Shift phase by -15 degrees @@ -10130,283 +9547,232 @@ Please make sure you have read-permission to the file and the directory containi - Click to shift phase by +15 degrees + Shift phase by +15 degrees + Normalize - - - Click to normalize - - + Invert - - - Click to invert - - + Smooth - - - Click to smooth - - + Sine wave - - - Click for sine wave - - + Triangle wave - - - Click for triangle wave - - - Click for saw wave + Saw wave - Square wave - - - - Click for square wave + Square wave Xpressive - + Selected graph - + A1 - + A2 - + A3 - + W1 smoothing - + W2 smoothing - + W3 smoothing - - - PAN1 - - - - - PAN2 - - - REL TRANS + Panning 1 + + + + + Panning 2 + + + + + Rel trans XpressiveView - + + Draw your own waveform here by dragging your mouse on this graph. + + + + Select oscillator W1 - + Select oscillator W2 - + Select oscillator W3 - - Select OUTPUT 1 + + Select output O1 - - Select OUTPUT 2 + + Select output O2 - + Open help window - + + Sine wave - - Click for a sine-wave. + + + Moog-saw wave - - Moog-Saw wave - - - - - Click for a Moog-Saw-wave. - - - - + + Exponential wave - - Click for an exponential wave. - - - - + + Saw wave - - Click here for a saw-wave. + + + User-defined wave - - User defined wave - - - - - Click here for a user-defined shape. - - - - + + Triangle wave - - Click here for a triangle-wave. - - - - + + Square wave - - Click here for a square-wave. - - - - - White noise wave - - - - - Click here for white-noise. - - - + + White noise + + + + WaveInterpolate - + ExpressionValid - + General purpose 1: - + General purpose 2: - + General purpose 3: - + O1 panning: - + O2 panning: - + Release transition: - + Smoothness @@ -10414,131 +9780,126 @@ Please make sure you have read-permission to the file and the directory containi ZynAddSubFxInstrument - + Portamento - - - Filter Frequency - - - Filter Resonance + Filter frequency - Bandwidth + Filter resonance - FM Gain + Bandwidth - Resonance Center Frequency + FM gain - Resonance Bandwidth + Resonance center frequency - Forward MIDI Control Change Events + Resonance bandwidth + + + + + Forward MIDI control change events ZynAddSubFxView - + Portamento: - + PORT - - - Filter Frequency: - - - - - FREQ - - - - - Filter Resonance: - - - - - RES - - - Bandwidth: + Filter frequency: - BW + FREQ - FM Gain: + Filter resonance: - FM GAIN + RES - Resonance center frequency: + Bandwidth: - RES CF + BW - Resonance bandwidth: + FM gain: - RES BW + FM GAIN - - Forward MIDI Control Changes + + Resonance center frequency: - Show GUI + RES CF + + + + + Resonance bandwidth: + + + + + RES BW + + + + + Forward MIDI control changes - Click here to show or hide the graphical user interface (GUI) of ZynAddSubFX. + Show GUI @@ -10608,100 +9969,72 @@ Please make sure you have read-permission to the file and the directory containi bitInvader - - Samplelength + + Sample length bitInvaderView - - Sample Length + + Sample length - + Draw your own waveform here by dragging your mouse on this graph. - + + Sine wave - - Click for a sine-wave. - - - - + + Triangle wave - - Click here for a triangle-wave. - - - - + + Saw wave - - Click here for a saw-wave. - - - - + + Square wave - - Click here for a square-wave. + + + White noise - - White noise wave + + + User-defined wave - - Click here for white-noise. + + + Smooth waveform - - User defined wave - - - - - Click here for a user-defined shape. - - - - - Smooth - - - - - Click here to smooth waveform. - - - - + Interpolation - + Normalize @@ -10750,47 +10083,31 @@ Please make sure you have read-permission to the file and the directory containi - Reset waveform - - - - Click here to reset the wavegraph back to default + Reset wavegraph - Smooth waveform - - - - Click here to apply smoothing to wavegraph + Smooth wavegraph - Increase wavegraph amplitude by 1dB - - - - Click here to increase wavegraph amplitude by 1dB + Increase wavegraph amplitude by 1 dB - Decrease wavegraph amplitude by 1dB - - - - Click here to decrease wavegraph amplitude by 1dB + Decrease wavegraph amplitude by 1 dB - Stereomode Maximum + Stereo mode: maximum @@ -10800,7 +10117,7 @@ Please make sure you have read-permission to the file and the directory containi - Stereomode Average + Stereo mode: average @@ -10810,7 +10127,7 @@ Please make sure you have read-permission to the file and the directory containi - Stereomode Unlinked + Stereo mode: unlinked @@ -10847,23 +10164,10 @@ Please make sure you have read-permission to the file and the directory containi - - fxLineLcdSpinBox - - - Assign to: - - - - - New FX Channel - - - graphModel - + Graph @@ -10887,12 +10191,12 @@ Please make sure you have read-permission to the file and the directory containi - Distortion Start + Start distortion - Distortion End + End distortion @@ -10902,7 +10206,7 @@ Please make sure you have read-permission to the file and the directory containi - Envelope Slope + Envelope slope @@ -10917,7 +10221,7 @@ Please make sure you have read-permission to the file and the directory containi - Frequency Slope + Frequency slope @@ -10945,7 +10249,7 @@ Please make sure you have read-permission to the file and the directory containi - Frequency Slope: + Frequency slope: @@ -10955,12 +10259,12 @@ Please make sure you have read-permission to the file and the directory containi - Envelope Length: + Envelope length: - Envelope Slope: + Envelope slope: @@ -10975,12 +10279,12 @@ Please make sure you have read-permission to the file and the directory containi - Distortion Start: + Start distortion: - Distortion End: + End distortion: @@ -11017,24 +10321,7 @@ Please make sure you have read-permission to the file and the directory containi - - This dialog displays information on all of the LADSPA plugins LMMS was able to locate. The plugins are divided into five categories based upon an interpretation of the port types and names. - -Available Effects are those that can be used by LMMS. In order for LMMS to be able to use an effect, it must, first and foremost, be an effect, which is to say, it has to have both input channels and output channels. LMMS identifies an input channel as an audio rate port containing 'in' in the name. Output channels are identified by the letters 'out'. Furthermore, the effect must have the same number of inputs and outputs and be real time capable. - -Unavailable Effects are those that were identified as effects, but either didn't have the same number of input and output channels or weren't real time capable. - -Instruments are plugins for which only output channels were identified. - -Analysis Tools are plugins for which only input channels were identified. - -Don't Knows are plugins for which no input or output channels were identified. - -Double clicking any of the plugins will bring up information on the ports. - - - - + Type: @@ -11139,57 +10426,57 @@ Double clicking any of the plugins will bring up information on the ports. lb302Synth - + VCF Cutoff Frequency - + VCF Resonance - + VCF Envelope Mod - + VCF Envelope Decay - + Distortion - + Waveform - + Slide Decay - + Slide - + Accent - + Dead - + 24dB/oct Filter @@ -11197,153 +10484,153 @@ Double clicking any of the plugins will bring up information on the ports. lb302SynthView - + Cutoff Freq: - + Resonance: - + Env Mod: - + Decay: - + 303-es-que, 24dB/octave, 3 pole filter - + Slide Decay: - + DIST: - + Saw wave - + Click here for a saw-wave. - + Triangle wave - + Click here for a triangle-wave. - + Square wave - + Click here for a square-wave. - + Rounded square wave - + Click here for a square-wave with a rounded end. - + Moog wave - + Click here for a moog-like wave. - + Sine wave - + Click for a sine-wave. - - + + White noise wave - + Click here for an exponential wave. - + Click here for white-noise. - + Bandlimited saw wave - + Click here for bandlimited saw wave. - + Bandlimited square wave - + Click here for bandlimited square wave. - + Bandlimited triangle wave - + Click here for bandlimited triangle wave. - + Bandlimited moog saw wave - + Click here for bandlimited moog saw wave. @@ -11362,17 +10649,17 @@ Double clicking any of the plugins will bring up information on the ports. - Vibrato Gain + Vibrato gain - Vibrato Freq + Vibrato frequency - Stick Mix + Stick mix @@ -11387,12 +10674,12 @@ Double clicking any of the plugins will bring up information on the ports. - LFO Speed + LFO speed - LFO Depth + LFO depth @@ -11442,7 +10729,7 @@ Double clicking any of the plugins will bring up information on the ports. - Wood1 + Wood 1 @@ -11452,7 +10739,7 @@ Double clicking any of the plugins will bring up information on the ports. - Wood2 + Wood 2 @@ -11462,7 +10749,7 @@ Double clicking any of the plugins will bring up information on the ports. - Two Fixed + Two fixed @@ -11472,17 +10759,17 @@ Double clicking any of the plugins will bring up information on the ports. - Tubular Bells + Tubular bells - Uniform Bar + Uniform bar - Tuned Bar + Tuned bar @@ -11492,7 +10779,7 @@ Double clicking any of the plugins will bring up information on the ports. - Tibetan Bowl + Tibetan bowl @@ -11545,32 +10832,32 @@ Double clicking any of the plugins will bring up information on the ports. - Vib Gain + Vibrato gain - Vib Gain: + Vibrato gain: - Vib Freq + Vibrato frequency - Vib Freq: + Vibrato frequency: - Stick Mix + Stick mix - Stick Mix: + Stick mix: @@ -11595,22 +10882,22 @@ Double clicking any of the plugins will bring up information on the ports. - LFO Speed + LFO speed - LFO Speed: + LFO speed: - LFO Depth + LFO depth - LFO Depth: + LFO depth: @@ -11647,91 +10934,61 @@ Double clicking any of the plugins will bring up information on the ports. manageVSTEffectView - + - VST parameter control - - VST Sync + + VST sync - - Click here if you want to synchronize all parameters with VST plugin. - - - - - + + Automated - - Click here if you want to display automated parameters only. - - - - + Close - - - Close VST effect knob-controller window. - - manageVestigeInstrumentView - - + + - VST plugin control - + VST Sync - - Click here if you want to synchronize all parameters with VST plugin. - - - - - + + Automated - - Click here if you want to display automated parameters only. - - - - + Close - - - Close VST plugin knob-controller window. - - organicInstrument - + Distortion - + Volume @@ -11739,63 +10996,48 @@ Double clicking any of the plugins will bring up information on the ports. organicInstrumentView - + Distortion: - - The distortion knob adds distortion to the output of the instrument. - - - - + Volume: - The volume knob controls the volume of the output of the instrument. It is cumulative with the instrument window's volume control. - - - - Randomise - - The randomize button randomizes all knobs except the harmonics,main volume and distortion knobs. - - - - - + + Osc %1 waveform: - + Osc %1 volume: - + Osc %1 panning: - + Osc %1 stereo detuning - + cents - + Osc %1 harmonic: @@ -11846,7 +11088,7 @@ Double clicking any of the plugins will bring up information on the ports. pluginBrowser - + no description @@ -11866,27 +11108,27 @@ Double clicking any of the plugins will bring up information on the ports. - + Customizable wavetable synthesizer - + An oversampling bitcrusher - + Carla Patchbay Instrument - + Carla Rack Instrument - + A 4-band Crossover Equalizer @@ -11901,22 +11143,22 @@ Double clicking any of the plugins will bring up information on the ports. - + plugin for processing dynamics in a flexible way - + A native eq plugin - + A native flanger plugin - + Emulation of GameBoy (TM) APU @@ -11926,7 +11168,7 @@ Double clicking any of the plugins will bring up information on the ports. - + Filter for importing Hydrogen files into LMMS @@ -11941,22 +11183,22 @@ Double clicking any of the plugins will bring up information on the ports. - + plugin for using arbitrary LADSPA-effects inside LMMS. - + Incomplete monophonic imitation tb303 - + Filter for exporting MIDI-files from LMMS - + Filter for importing MIDI-files into LMMS @@ -11976,12 +11218,12 @@ Double clicking any of the plugins will bring up information on the ports. - + 2-operator FM Synth - + Additive Synthesizer for organ-like sounds @@ -11991,12 +11233,12 @@ Double clicking any of the plugins will bring up information on the ports. - + Plugin for controlling knobs with sound peaks - + Reverb algorithm by Sean Costello @@ -12006,21 +11248,16 @@ Double clicking any of the plugins will bring up information on the ports. - + LMMS port of sfxr - + Emulation of the MOS6581 and MOS8580 SID. This chip was used in the Commodore 64 computer. - - - Graphical spectrum analyzer plugin - - Plugin for enhancing stereo separation of a stereo input file @@ -12042,12 +11279,12 @@ This chip was used in the Commodore 64 computer. - + VST-host for using VST(i)-plugins within LMMS - + Vibrating string modeler @@ -12062,20 +11299,25 @@ This chip was used in the Commodore 64 computer. - + plugin for waveshaping - + Mathematical expression parser - + Embedded ZynAddSubFX + + + A graphical spectrum analyzer. + + sf2Instrument @@ -12101,22 +11343,22 @@ This chip was used in the Commodore 64 computer. - Reverb Roomsize + Reverb room size - Reverb Damping + Reverb damping - Reverb Width + Reverb width - Reverb Level + Reverb level @@ -12126,26 +11368,26 @@ This chip was used in the Commodore 64 computer. - Chorus Lines + Chorus voices - Chorus Level + Chorus level - Chorus Speed + Chorus speed - Chorus Depth + Chorus depth - + A soundfont %1 could not be loaded. @@ -12153,92 +11395,69 @@ This chip was used in the Commodore 64 computer. sf2InstrumentView - - Open other SoundFont file - - - - - Click here to open another SF2 file - - - - - Choose the patch - - - - - Gain - - - - - Apply reverb (if supported) - - - - - This button enables the reverb effect. This is useful for cool effects, but only works on files that support it. - - - - - Reverb Roomsize: - - - - - Reverb Damping: - - - - - Reverb Width: - - - - - Reverb Level: - - - - - Apply chorus (if supported) - - - - - This button enables the chorus effect. This is useful for cool echo effects, but only works on files that support it. - - - - - Chorus Lines: - - - - - Chorus Level: - - - - - Chorus Speed: - - - - - Chorus Depth: - - - - + + Open SoundFont file - + + Choose patch + + + + + Gain: + + + + + Apply reverb (if supported) + + + + + Room size: + + + + + Damping: + + + + + Width: + + + + + + Level: + + + + + Apply chorus (if supported) + + + + + Voices: + + + + + Speed: + + + + + Depth: + + + + SoundFont Files (*.sf2 *.sf3) @@ -12246,40 +11465,40 @@ This chip was used in the Commodore 64 computer. sfxrInstrument - - Wave Form + + Wave sidInstrument - - - Cutoff - - - Resonance + Cutoff frequency + Resonance + + + + Filter type - + Voice 3 off - + Volume - + Chip model @@ -12287,173 +11506,127 @@ This chip was used in the Commodore 64 computer. sidInstrumentView - + Volume: - + Resonance: - - + + Cutoff frequency: - - High-Pass filter + + High-pass filter - - Band-Pass filter + + Band-pass filter - - Low-Pass filter + + Low-pass filter - - Voice3 Off + + Voice 3 off - + MOS6581 SID - + MOS8580 SID - - + + Attack: - - Attack rate determines how rapidly the output of Voice %1 rises from zero to peak amplitude. - - - - - + + Decay: - - Decay rate determines how rapidly the output falls from the peak amplitude to the selected Sustain level. - - - - + Sustain: - - Output of Voice %1 will remain at the selected Sustain amplitude as long as the note is held. - - - - - + + Release: - - The output of of Voice %1 will fall from Sustain amplitude to zero amplitude at the selected Release rate. - - - - - + Pulse Width: - - The Pulse Width resolution allows the width to be smoothly swept with no discernable stepping. The Pulse waveform on Oscillator %1 must be selected to have any audible effect. - - - - + Coarse: - - The Coarse detuning allows to detune Voice %1 one octave up or down. + + Pulse wave - - Pulse Wave + + Triangle wave - - Triangle Wave + + Saw wave - - SawTooth - - - - + Noise - + Sync - - Sync synchronizes the fundamental frequency of Oscillator %1 with the fundamental frequency of Oscillator %2 producing "Hard Sync" effects. + + Ring modulation - - Ring-Mod - - - - - Ring-mod replaces the Triangle Waveform output of Oscillator %1 with a "Ring Modulated" combination of Oscillators %1 and %2. - - - - + Filtered - - When Filtered is on, Voice %1 will be processed through the Filter. When Filtered is off, Voice %1 appears directly at the output, and the Filter has no effect on it. - - - - + Test - - Test, when set, resets and locks Oscillator %1 at zero until Test is turned off. + + Pulse width: @@ -12461,7 +11634,7 @@ This chip was used in the Commodore 64 computer. stereoEnhancerControlDialog - WIDE + WIDTH @@ -12524,360 +11697,264 @@ This chip was used in the Commodore 64 computer. + + testcontext + + + + test string + + + + + + test plural %n + + + + + vestigeInstrument - + Loading plugin - - Please wait while loading VST-plugin... + + Please wait while loading the VST plugin... vibed - + String %1 volume - + String %1 stiffness - + Pick %1 position - + Pickup %1 position - - Pan %1 + + String %1 panning - - Detune %1 + + String %1 detune - - Fuzziness %1 + + String %1 fuzziness - - Length %1 + + String %1 length - + Impulse %1 - - Octave %1 + + String %1 vibedView - - Volume: + + String volume: - - The 'V' knob sets the volume of the selected string. - - - - + String stiffness: - The 'S' knob sets the stiffness of the selected string. The stiffness of the string affects how long the string will ring out. The lower the setting, the longer the string will ring. - - - - Pick position: - - The 'P' knob sets the position where the selected string will be 'picked'. The lower the setting the closer the pick is to the bridge. - - - - + Pickup position: + + + String panning: + + + + + String detune: + + - The 'PU' knob sets the position where the vibrations will be monitored for the selected string. The lower the setting, the closer the pickup is to the bridge. + String fuzziness: - - Pan: + + String length: - - The Pan knob determines the location of the selected string in the stereo field. + + Impulse - - Detune: - - - - - The Detune knob modifies the pitch of the selected string. Settings less than zero will cause the string to sound flat. Settings greater than zero will cause the string to sound sharp. - - - - - Fuzziness: - - - - - The Slap knob adds a bit of fuzz to the selected string which is most apparent during the attack, though it can also be used to make the string sound more 'metallic'. - - - - - Length: - - - - - The Length knob sets the length of the selected string. Longer strings will both ring longer and sound brighter, however, they will also eat up more CPU cycles. - - - - - Impulse or initial state - - - - - The 'Imp' selector determines whether the waveform in the graph is to be treated as an impulse imparted to the string by the pick or the initial state of the string. - - - - + Octave - - The Octave selector is used to choose which harmonic of the note the string will ring at. For example, '-2' means the string will ring two octaves below the fundamental, 'F' means the string will ring at the fundamental, and '6' means the string will ring six octaves above the fundamental. - - - - + Impulse Editor - - The waveform editor provides control over the initial state or impulse that is used to start the string vibrating. The buttons to the right of the graph will initialize the waveform to the selected type. The '?' button will load a waveform from a file--only the first 128 samples will be loaded. - -The waveform can also be drawn in the graph. - -The 'S' button will smooth the waveform. - -The 'N' button will normalize the waveform. - - - - - Vibed models up to nine independently vibrating strings. The 'String' selector allows you to choose which string is being edited. The 'Imp' selector chooses whether the graph represents an impulse or the initial state of the string. The 'Octave' selector chooses which harmonic the string should vibrate at. - -The graph allows you to control the initial state or impulse used to set the string in motion. - -The 'V' knob controls the volume. The 'S' knob controls the string's stiffness. The 'P' knob controls the pick position. The 'PU' knob controls the pickup position. - -'Pan' and 'Detune' hopefully don't need explanation. The 'Slap' knob adds a bit of fuzz to the sound of the string. - -The 'Length' knob controls the length of the string. - -The LED in the lower right corner of the waveform editor determines whether the string is active in the current instrument. - - - - + Enable waveform - - Click here to enable/disable waveform. + + Enable/disable string - + String - - The String selector is used to choose which string the controls are editing. A Vibed instrument can contain up to nine independently vibrating strings. The LED in the lower right corner of the waveform editor indicates whether the selected string is active. - - - - + + Sine wave - - Use a sine-wave for current oscillator. - - - - + + Triangle wave - - Use a triangle-wave for current oscillator. - - - - + + Saw wave - - Use a saw-wave for current oscillator. - - - - + + Square wave - - Use a square-wave for current oscillator. + + + White noise - - White noise wave + + + User-defined wave - - Use white-noise for current oscillator. + + + Smooth waveform - - User defined wave - - - - - Use a user-defined waveform for current oscillator. - - - - - Smooth - - - - - Click here to smooth waveform. - - - - - Normalize - - - - - Click here to normalize waveform. + + + Normalize waveform voiceObject - + Voice %1 pulse width - + Voice %1 attack - + Voice %1 decay - + Voice %1 sustain - + Voice %1 release - + Voice %1 coarse detuning - + Voice %1 wave shape - + Voice %1 sync - + Voice %1 ring modulate - + Voice %1 filtered - + Voice %1 test @@ -12906,42 +11983,26 @@ The LED in the lower right corner of the waveform editor determines whether the - Reset waveform - - - - Click here to reset the wavegraph back to default + Reset wavegraph - Smooth waveform - - - - Click here to apply smoothing to wavegraph + Smooth wavegraph - Increase graph amplitude by 1dB - - - - Click here to increase wavegraph amplitude by 1dB + Increase wavegraph amplitude by 1 dB - Decrease graph amplitude by 1dB - - - - Click here to decrease wavegraph amplitude by 1dB + Decrease wavegraph amplitude by 1 dB @@ -12951,7 +12012,7 @@ The LED in the lower right corner of the waveform editor determines whether the - Clip input signal to 0dB + Clip input signal to 0 dB diff --git a/data/locale/es.ts b/data/locale/es.ts index c4d5178f1..f6cfaf832 100644 --- a/data/locale/es.ts +++ b/data/locale/es.ts @@ -704,11 +704,11 @@ Si te interesa traducir LMMS a otros idiomas o mejorar las traducciones existent BitcrushControlDialog IN - ENTRADA + IN OUT - SALIDA + OUT GAIN @@ -728,7 +728,7 @@ Si te interesa traducir LMMS a otros idiomas o mejorar las traducciones existent CLIP - RECORTE + CLIP Output Clip: @@ -1031,7 +1031,7 @@ Si te interesa traducir LMMS a otros idiomas o mejorar las traducciones existent DELAY - RETRASO + DELAY FDBK diff --git a/data/locale/fa.ts b/data/locale/fa.ts index 9f6ec278b..fe9d2ca6b 100644 --- a/data/locale/fa.ts +++ b/data/locale/fa.ts @@ -1218,7 +1218,7 @@ If you're interested in translating LMMS in another language or want to imp DECAY - محو-DECAY + DECAY Time: @@ -1360,7 +1360,7 @@ Right clicking will bring up a context menu where you can change the order in wh HOLD - نگهداری-HOLD + HOLD Hold: diff --git a/data/locale/fr.ts b/data/locale/fr.ts index ddfbb1ea3..f8209d5d1 100644 --- a/data/locale/fr.ts +++ b/data/locale/fr.ts @@ -703,11 +703,11 @@ Si vous êtes intéressé par la traduction de LMMS dans une nouvelle langue ou BitcrushControlDialog IN - ENTRÉE + IN OUT - SORTIE + OUT GAIN @@ -2252,7 +2252,7 @@ Veuillez vous assurez que vous avez les droits d'écriture sur le fichier e DELAY - DE RETARD + DELAY RATE diff --git a/data/locale/gl.ts b/data/locale/gl.ts index a7843d081..657ed1291 100644 --- a/data/locale/gl.ts +++ b/data/locale/gl.ts @@ -1468,7 +1468,7 @@ Ao premer co botón dereito aparece un menú de contexto no que se pode cambiar EnvelopeAndLfoView DEL - TMP REV + DEL Predelay: @@ -1540,7 +1540,7 @@ Ao premer co botón dereito aparece un menú de contexto no que se pode cambiar AMT - CANTIDADE + AMT Modulation amount: diff --git a/data/locale/it.ts b/data/locale/it.ts index 6931b8421..f93cb0170 100644 --- a/data/locale/it.ts +++ b/data/locale/it.ts @@ -1030,7 +1030,7 @@ Se sei interessato a tradurre LMMS o vuoi migliorare una traduzione esistente, s DELAY - RITARDO + DELAY FDBK @@ -1038,7 +1038,7 @@ Se sei interessato a tradurre LMMS o vuoi migliorare una traduzione esistente, s RATE - FREQUENZA + RATE AMNT @@ -2252,11 +2252,11 @@ Si prega di controllare i permessi di scrittura sul file e la cartella che lo co DELAY - RITARDO + DELAY RATE - FREQUENZA + RATE AMNT diff --git a/data/locale/ja.ts b/data/locale/ja.ts index 4355aef58..b7c1a780c 100644 --- a/data/locale/ja.ts +++ b/data/locale/ja.ts @@ -3377,7 +3377,7 @@ You can remove and move FX channels in the context menu, which is accessed by ri PAN - パニング + PAN MIDI @@ -6142,7 +6142,7 @@ Reason: "%2" PAN - パニング + PAN diff --git a/data/locale/ko.ts b/data/locale/ko.ts index 36fe2e214..a6b450a9e 100644 --- a/data/locale/ko.ts +++ b/data/locale/ko.ts @@ -1,4 +1,6 @@ - + + + AboutDialog @@ -6,42 +8,17 @@ LMMS에 대하여 - Version %1 (%2/%3, Qt %4, %5) - 버전 %1 (%2/%3, Qt %4, %5) + LMMS + LMMS About 정보 - - LMMS - easy music production for everyone - LMMS - 누구나 쉽게 할 수 있는 음악 제작 - Authors 개발자 - - Translation - 번역 - - - Current language not translated (or native English). - -If you're interested in translating LMMS in another language or want to improve existing translations, you're welcome to help us! Simply contact the maintainer! - 송현진 (Hyunjin Song) <tteu.ingog@gmail.com> -방성범 (Bang Seongbeom) <bangseongbeom@gmail.com> - -LMMS를 다른 언어로 번역하고 싶다거나 기존 번역을 개선하고 싶다면 저희를 도와주세요! LMMS 관리자와의 연락을 통해 참여하실 수 있습니다. - - - License - 라이선스 - - - LMMS - LMMS - Involved 기여자 @@ -51,23 +28,47 @@ LMMS를 다른 언어로 번역하고 싶다거나 기존 번역을 개선하고 기여자 (기여 순으로 정렬): - Copyright © %1 - Copyright © %1 + Translation + 번역 - <html><head/><body><p><a href="https://lmms.io"><span style=" text-decoration: underline; color:#0000ff;">https://lmms.io</span></a></p></body></html> - <html><head/><body><p><a href="https://lmms.io"><span style=" text-decoration: underline; color:#0000ff;">https://lmms.io</span></a></p></body></html> + License + 라이선스 + + + Version %1 (%2/%3, Qt %4, %5). + 버전 %1 (%2/%3, Qt %4, %5). + + + LMMS - easy music production for everyone. + LMMS - 누구나 쉽게 할 수 있는 음악 제작. + + + Copyright © %1. + Copyright © %1. + + + <html><head/><body><p><a href="https://lmms.io"><span style=" text-decoration: underline; color:#33cc33;">https://lmms.io</span></a></p></body></html> + <html><head/><body><p><a href="https://lmms.io"><span style=" text-decoration: underline; color:#33cc33;">https://lmms.io</span></a></p></body></html> + + + Current language not translated (or native English). +If you're interested in translating LMMS in another language or want to improve existing translations, you're welcome to help us! Simply contact the maintainer! + 송현진 (Hyunjin Song) <tteu.ingog@gmail.com> +방성범 (Bang Seongbeom) <bangseongbeom@gmail.com> + +LMMS를 다른 언어로 번역하고 싶다거나 기존 번역을 개선하고 싶다면 저희를 도와주세요! LMMS 관리자와의 연락을 통해 참여하실 수 있습니다. AmplifierControlDialog VOL - 볼륨 + 음량 Volume: - 볼륨: + 음량: PAN @@ -98,7 +99,7 @@ LMMS를 다른 언어로 번역하고 싶다거나 기존 번역을 개선하고 AmplifierControls Volume - 볼륨 + 음량 Panning @@ -126,81 +127,45 @@ LMMS를 다른 언어로 번역하고 싶다거나 기존 번역을 개선하고 AudioFileProcessorView - - Open other sample - 다른 샘플 열기 - - - Click here, if you want to open another audio-file. A dialog will appear where you can select your file. Settings like looping-mode, start and end-points, amplify-value, and so on are not reset. So, it may not sound like the original sample. - 클릭하여 다른 오디오 파일을 선택합니다. 클릭하면 파일을 선택할 수 있는 창이 나타납니다. 루프 모드, 시작점, 끝점, 증폭 등의 설정은 자동으로 초기화되지 않으므로 원본 오디오 파일과 다르게 들릴 수 있습니다. - Reverse sample 샘플 역으로 - - If you enable this button, the whole sample is reversed. This is useful for cool effects, e.g. a reversed crash. - 이 버튼이 활성화되면 샘플을 역으로 재생합니다. 리버스 크래시와 같은 효과에 사용할 수 있습니다. - - - Amplify: - 증폭: - - - With this knob you can set the amplify ratio. When you set a value of 100% your sample isn't changed. Otherwise it will be amplified up or down (your actual sample-file isn't touched!) - 이 노브를 이용하여 증폭률을 설정할 수 있습니다. 값을 100%로 설정하면 샘플은 그대로 재생됩니다. 그렇지 않은 경우 샘플의 음량이 증가되거나 감소됩니다. (실제 샘플 파일에는 변화가 없습니다) - - - Startpoint: - 시작점: - - - Endpoint: - 끝점: - - - Continue sample playback across notes - 샘플을 여러 음표에 걸쳐 계속 재생 - - - Enabling this option makes the sample continue playing across different notes - if you change pitch, or the note length stops before the end of the sample, then the next note played will continue where it left off. To reset the playback to the start of the sample, insert a note at the bottom of the keyboard (< 20 Hz) - 이 옵션을 활성화하면 샘플이 여러 음표에 걸쳐 계속 재생됩니다 - 음표가 끝나기 전에 샘플이 끝나는 경우나 피치가 바뀌는 경우 다음 음표는 직전 음표의 재생이 끝난 곳부터 재생됩니다. 음표가 다시 처음부터 재생되게 하려면 매우 낮은 음표를 삽입하세요. (< 20Hz) - Disable loop 반복 비활성화 - - This button disables looping. The sample plays only once from start to end. - 이 버튼은 반복을 비활성화합니다. 샘플은 처음부터 끝까지 한 번만 재생됩니다. - Enable loop 반복 활성화 - This button enables forwards-looping. The sample loops between the end point and the loop point. - 이 버튼은 단방향 반복을 활성화합니다. 샘플은 반복 시작점과 끝점 사이에서 단방향으로 반복 재생됩니다. + Continue sample playback across notes + 샘플을 여러 음표에 걸쳐 계속 재생 - This button enables ping-pong-looping. The sample loops backwards and forwards between the end point and the loop point. - 이 버튼은 양방향 반복을 활성화합니다. 샘플은 반복 시작점과 끝점 사이에서 양방향으로 반복 재생됩니다. - - - With this knob you can set the point where AudioFileProcessor should begin playing your sample. - 이 노브를 이용하여 샘플 재생 시작점을 설정할 수 있습니다. - - - With this knob you can set the point where AudioFileProcessor should stop playing your sample. - 이 노브를 이용하여 샘플 재생 끝점을 설정할 수 있습니다. + Amplify: + 증폭: Loopback point: 루프 시작점: - With this knob you can set the point where the loop starts. - 이 노브를 이용하여 샘플 반복 시작점을 설정할 수 있습니다. + Open sample + 샘플 열기 + + + Enable ping-pong loop + 양방향 반복 활성화 + + + Start point: + 시작점: + + + End point: + 끝점: @@ -238,7 +203,7 @@ LMMS를 다른 언어로 번역하고 싶다거나 기존 번역을 개선하고 - AudioOss::setupWidget + AudioOss DEVICE 장치 @@ -260,7 +225,7 @@ LMMS를 다른 언어로 번역하고 싶다거나 기존 번역을 개선하고 - AudioPulseAudio::setupWidget + AudioPulseAudio DEVICE 장치 @@ -278,7 +243,7 @@ LMMS를 다른 언어로 번역하고 싶다거나 기존 번역을 개선하고 - AudioSndio::setupWidget + AudioSndio DEVICE 장치 @@ -317,6 +282,14 @@ LMMS를 다른 언어로 번역하고 싶다거나 기존 번역을 개선하고 Edit song-global automation 전역 오토메이션 편집 + + Remove song-global automation + 전역 오토메이션 제거 + + + Remove all linked controls + 연결 제거 + Connected to %1 %1에 연결됨 @@ -338,12 +311,8 @@ LMMS를 다른 언어로 번역하고 싶다거나 기존 번역을 개선하고 컨트롤러에 연결... - Remove song-global automation - 전역 오토메이션 제거 - - - Remove all linked controls - 연결 제거 + &Paste value + 값 붙여넣기(&P) @@ -367,17 +336,13 @@ LMMS를 다른 언어로 번역하고 싶다거나 기존 번역을 개선하고 Play/pause current pattern (Space) 현재 패턴 재생/일시정지 (Space) - - Click here if you want to play the current pattern. This is useful while editing it. The pattern is automatically looped when the end is reached. - 현재 패턴을 재생하려면 여기를 클릭하세요. 패턴의 끝에 도달하면 자동으로 반복 재생됩니다. - Stop playing of current pattern (Space) 현재 패턴 정지 (Space) - Click here if you want to stop playing of the current pattern. - 현재 패턴의 재생을 정지하려면 여기를 클릭하세요. + Edit actions + 편집 동작 Draw mode (Shift+D) @@ -396,20 +361,8 @@ LMMS를 다른 언어로 번역하고 싶다거나 기존 번역을 개선하고 좌우 반전 - Click here and the pattern will be inverted.The points are flipped in the y direction. - 여기를 클릭하면 패턴이 상하로 반전됩니다. - - - Click here and the pattern will be reversed. The points are flipped in the x direction. - 여기를 클릭하면 패턴이 좌우로 반전됩니다. - - - Click here and draw-mode will be activated. In this mode you can add and move single values. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. - 여기를 클릭하면 그리기 모드가 활성화됩니다. 그리기 모드에서는 값을 추가하거나 이동할 수 있습니다. 이 모드는 대부분의 경우에 사용되는 기본 모드입니다. 'Shift+D' 키를 눌러 이 모드를 활성화할 수도 있습니다. - - - Click here and erase-mode will be activated. In this mode you can erase single values. You can also press 'Shift+E' on your keyboard to activate this mode. - 여기를 클릭하면 지우기 모드가 활성화됩니다. 지우기 모드에서는 값을 삭제할 수 있습니다. 'Shift+E' 키를 눌러 이 모드를 활성화할 수도 있습니다. + Interpolation controls + Discrete progression @@ -425,23 +378,11 @@ LMMS를 다른 언어로 번역하고 싶다거나 기존 번역을 개선하고 Tension value for spline - + - A higher tension value may make a smoother curve but overshoot some values. A low tension value will cause the slope of the curve to level off at each control point. - - - - Click here to choose discrete progressions for this automation pattern. The value of the connected object will remain constant between control points and be set immediately to the new value when each control point is reached. - 클릭하여 이 패턴을 이산적 진행으로 설정합니다. 각 점 사이에서 값은 상수로 유지되며 새 점에 도달하는 순간 값이 갱신됩니다. - - - Click here to choose linear progressions for this automation pattern. The value of the connected object will change at a steady rate over time between control points to reach the correct value at each control point without a sudden change. - 클릭하여 이 패턴을 선형 진행으로 설정합니다. 각 점 사이에서 값은 일정한 비율로 변화하며 새 점에 도달하는 순간에 불연속적 값 변화가 없습니다. - - - Click here to choose cubic hermite progressions for this automation pattern. The value of the connected object will change in a smooth curve and ease in to the peaks and valleys. - 클릭하여 이 패턴을 3차 에르미트 진행으로 설정합니다. 각 점 사이에서 값은 매끄러운 곡선의 형태로 변화합니다.Save + Tension: + 장력: Cut selected values (%1+X) @@ -456,20 +397,16 @@ LMMS를 다른 언어로 번역하고 싶다거나 기존 번역을 개선하고 선택된 값 붙여넣기 (%1+V) - Click here and selected values will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. - + Zoom controls + - Click here and selected values will be copied into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. - + Quantization controls + - Click here and the values from the clipboard will be pasted at the first visible measure. - - - - Tension: - 장력: + Quantization + Automation Editor - no pattern @@ -479,37 +416,17 @@ LMMS를 다른 언어로 번역하고 싶다거나 기존 번역을 개선하고 Automation Editor - %1 오토메이션 편집기 - %1 - - Edit actions - 편집 동작 - - - Interpolation controls - - - - Timeline controls - - - - Zoom controls - - - - Quantization controls - - Model is already connected to this pattern. 대상이 이미 패턴에 연결되어 있습니다. - Quantization - + Horizontal zooming + - Quantization. Sets the smallest step size for the Automation Point. By default this also sets the length, clearing out other points in the range. Press <Ctrl> to override this behaviour. - + Vertical zooming + @@ -537,14 +454,6 @@ LMMS를 다른 언어로 번역하고 싶다거나 기존 번역을 개선하고 Change name 이름 바꾸기 - - %1 Connections - %1개의 연결 - - - Disconnect "%1" - "%1" 연결 해제 - Set/clear record 녹음 설정/해제 @@ -557,6 +466,14 @@ LMMS를 다른 언어로 번역하고 싶다거나 기존 번역을 개선하고 Flip Horizontally (Visible) 좌우 반전 + + %1 Connections + %1개의 연결 + + + Disconnect "%1" + "%1" 연결 해제 + Model is already connected to this pattern. 대상이 이미 패턴과 연결되어 있습니다. @@ -584,44 +501,36 @@ LMMS를 다른 언어로 번역하고 싶다거나 기존 번역을 개선하고 현재 비트/베이스 라인 정지 (Space) - Click here to play the current beat/bassline. The beat/bassline is automatically looped when its end is reached. - 클릭하여 비트/베이스 라인을 재생합니다. 자동으로 반복 재생됩니다. + Beat selector + 비트 선택기 - Click here to stop playing of current beat/bassline. - 클릭하여 비트/베이스 라인 재생을 정지합니다. + Track and step actions + Add beat/bassline 비트/베이스 라인 추가 + + Add sample-track + 샘플 트랙 추가 + Add automation-track 오토메이션 트랙 추가 Remove steps - 단계 제거 + Add steps - 단계 더하기 - - - Beat selector - - - - Track and step actions - + Clone Steps - - - - Add sample-track - 샘플 트랙 추가 + @@ -678,11 +587,11 @@ LMMS를 다른 언어로 번역하고 싶다거나 기존 번역을 개선하고 RATIO - + 비율 Ratio: - + 비율: @@ -697,7 +606,7 @@ LMMS를 다른 언어로 번역하고 싶다거나 기존 번역을 개선하고 Ratio - + 비율 @@ -715,79 +624,107 @@ LMMS를 다른 언어로 번역하고 싶다거나 기존 번역을 개선하고 이득 - Input Gain: - 입력 이득: - - - Input Noise: - - - - Output Gain: - 출력 이득: + NOISE + 잡음 CLIP - - - - Output Clip: - - - - Rate Enabled - - - - Enable samplerate-crushing - - - - Depth Enabled - - - - Enable bitdepth-crushing - - - - Sample rate: - 샘플 레이트: - - - Stereo difference: - - - - Levels: - - - - NOISE - 잡음 + 클리핑 FREQ 주파수 + + Sample rate: + 샘플 레이트: + STEREO 스테레오 + + Stereo difference: + 좌우 차이: + QUANT - + + + + Levels: + + + + Input gain: + 입력 이득: + + + Input noise: + + + + Output gain: + 출력 이득: + + + Output clip: + + + + Rate enabled + + + + Enable sample-rate crushing + + + + Depth enabled + + + + Enable bit-depth crushing + - CaptionMenu + BitcrushControls - &Help - 도움말(&H) + Input gain + 입력 이득 - Help (not available) - 도움말 사용 불가 + Input noise + + + + Output gain + 출력 이득 + + + Output clip + + + + Sample rate + + + + Stereo difference + + + + Levels + + + + Rate enabled + + + + Depth enabled + @@ -796,10 +733,6 @@ LMMS를 다른 언어로 번역하고 싶다거나 기존 번역을 개선하고 Show GUI GUI 표시 - - Click here to show or hide the graphical user interface (GUI) of Carla. - 클릭하여 Carla의 GUI를 표시하거나 숨깁니다. - Controller @@ -840,7 +773,7 @@ LMMS를 다른 언어로 번역하고 싶다거나 기존 번역을 개선하고 MIDI-devices to receive MIDI-events from - + USER CONTROLLER @@ -848,7 +781,7 @@ LMMS를 다른 언어로 번역하고 싶다거나 기존 번역을 개선하고 MAPPING FUNCTION - + 매핑 함수 OK @@ -892,10 +825,6 @@ LMMS를 다른 언어로 번역하고 싶다거나 기존 번역을 개선하고 Controls 컨트롤 - - Controllers are able to automate the value of a knob, slider, and other controls. - 컨트롤러를 통하여 노브, 슬라이더 등의 값을 자동으로 제어할 수 있습니다. - Rename controller 컨트롤러 이름 바꾸기 @@ -904,6 +833,10 @@ LMMS를 다른 언어로 번역하고 싶다거나 기존 번역을 개선하고 Enter the new name for this controller 컨트롤러의 새 이름을 입력하세요 + + LFO + LFO + &Remove this controller 컨트롤러 제거(&R) @@ -912,158 +845,154 @@ LMMS를 다른 언어로 번역하고 싶다거나 기존 번역을 개선하고 Re&name this controller 컨트롤러 이름 바꾸기(&N) - - LFO - LFO - CrossoverEQControlDialog - Band 1/2 Crossover: - + Band 1/2 crossover: + - Band 2/3 Crossover: - + Band 2/3 crossover: + - Band 3/4 Crossover: - + Band 3/4 crossover: + - Band 1 Gain: - + Band 1 gain + - Band 2 Gain: - + Band 1 gain: + - Band 3 Gain: - + Band 2 gain + - Band 4 Gain: - + Band 2 gain: + - Band 1 Mute - + Band 3 gain + - Mute Band 1 - + Band 3 gain: + - Band 2 Mute - + Band 4 gain + - Mute Band 2 - + Band 4 gain: + - Band 3 Mute - + Band 1 mute + - Mute Band 3 - + Mute band 1 + - Band 4 Mute - + Band 2 mute + - Mute Band 4 - + Mute band 2 + + + + Band 3 mute + + + + Mute band 3 + + + + Band 4 mute + + + + Mute band 4 + DelayControls - - Delay Samples - - Feedback 피드백 - - Lfo Frequency - LFO 주파수 - - - Lfo Amount - - Output gain 출력 이득 + + Delay samples + + + + LFO frequency + LFO 주파수 + + + LFO amount + + DelayControlsDialog - Lfo Amt - + DELAY + 지연 - Delay Time - + FDBK + 피드백 - Feedback Amount - + RATE + - Lfo - - - - Out Gain - 출력 이득 + AMNT + Gain 이득 - DELAY - + Delay time + - FDBK - + Feedback amount + - RATE - + LFO frequency + - AMNT - + LFO amount + + + + Out gain + 출력 이득 DualFilterControlDialog - - Filter 1 enabled - 필터 1 활성화됨 - - - Filter 2 enabled - 필터 2 활성화됨 - - - Click to enable/disable Filter 1 - 클릭하여 필터 1 활성화/비활성화 - - - Click to enable/disable Filter 2 - 클릭하여 필터 2 활성화/비활성화 - FREQ 주파수 @@ -1090,11 +1019,27 @@ LMMS를 다른 언어로 번역하고 싶다거나 기존 번역을 개선하고 MIX - + Mix - + + + + Filter 1 enabled + 필터 1 활성화됨 + + + Filter 2 enabled + 필터 2 활성화됨 + + + Enable/disable filter 1 + + + + Enable/disable filter 2 + @@ -1107,21 +1052,17 @@ LMMS를 다른 언어로 번역하고 싶다거나 기존 번역을 개선하고 Filter 1 type 필터 1 종류 - - Cutoff 1 frequency - - Q/Resonance 1 - + 필터 1 Q/공명 Gain 1 - + 이득 1 Mix - + Filter 2 enabled @@ -1131,109 +1072,117 @@ LMMS를 다른 언어로 번역하고 싶다거나 기존 번역을 개선하고 Filter 2 type 필터 2 종류 - - Cutoff 2 frequency - - Q/Resonance 2 - + Q/공명 2 Gain 2 - - - - LowPass - - - - HiPass - - - - BandPass csg - - - - BandPass czpg - + 이득 2 Notch - - - - Allpass - + 노치 Moog - - - - 2x LowPass - - - - RC LowPass 12dB - - - - RC BandPass 12dB - - - - RC HighPass 12dB - - - - RC LowPass 24dB - - - - RC BandPass 24dB - - - - RC HighPass 24dB - - - - Vocal Formant Filter - + Moog 2x Moog - - - - SV LowPass - - - - SV BandPass - - - - SV HighPass - + 2x Moog SV Notch - + SV 노치 Fast Formant - + Tripole - + + + + Cutoff frequency 1 + + + + Cutoff frequency 2 + + + + Low-pass + + + + Hi-pass + + + + Band-pass csg + + + + Band-pass czpg + + + + All-pass + + + + 2x Low-pass + + + + RC Low-pass 12 dB/oct + + + + RC Band-pass 12 dB/oct + + + + RC High-pass 12 dB/oct + + + + RC Low-pass 24 dB/oct + + + + RC Band-pass 24 dB/oct + + + + RC High-pass 24 dB/oct + + + + Vocal Formant + + + + SV Low-pass + + + + SV Band-pass + + + + SV High-pass + Editor + + Transport controls + + Play (Space) 재생 (Space) @@ -1248,11 +1197,11 @@ LMMS를 다른 언어로 번역하고 싶다거나 기존 번역을 개선하고 Record while playing - + 재생하면서 녹음 - Transport controls - + Toggle Step Recording + @@ -1263,7 +1212,7 @@ LMMS를 다른 언어로 번역하고 싶다거나 기존 번역을 개선하고 Wet/Dry mix - + Gate @@ -1271,7 +1220,7 @@ LMMS를 다른 언어로 번역하고 싶다거나 기존 번역을 개선하고 Decay - + @@ -1312,42 +1261,30 @@ LMMS를 다른 언어로 번역하고 싶다거나 기존 번역을 개선하고 Author - + 개발자 EffectView - - Toggles the effect on or off. - 효과를 켜거나 끕니다. - On/Off 켬/끔 W/D - + Wet Level: - - - - The Wet/Dry knob sets the ratio between the input signal and the effect signal that forms the output. - + DECAY - + Time: - - - - The Decay knob controls how many buffers of silence must pass before the plugin stops processing. Smaller values will reduce the CPU overhead but run the risk of clipping the tail on delay and reverb effects. - + GATE @@ -1357,30 +1294,10 @@ LMMS를 다른 언어로 번역하고 싶다거나 기존 번역을 개선하고 Gate: 게이트: - - The Gate knob controls the signal level that is considered to be 'silence' while deciding when to stop processing signals. - - Controls 컨트롤 - - Effect plugins function as a chained series of effects where the signal will be processed from top to bottom. - -The On/Off switch allows you to bypass a given plugin at any point in time. - -The Wet/Dry knob controls the balance between the input signal and the effected signal that is the resulting output from the effect. The input for the stage is the output from the previous stage. So, the 'dry' signal for effects lower in the chain contains all of the previous effects. - -The Decay knob controls how long the signal will continue to be processed after the notes have been released. The effect will stop processing signals when the volume has dropped below a given threshold for a given length of time. This knob sets the 'given length of time'. Longer times will require more CPU, so this number should be set low for most effects. It needs to be bumped up for effects that produce lengthy periods of silence, e.g. delays. - -The Gate knob controls the 'given threshold' for the effect's auto shutdown. The clock for the 'given length of time' will begin as soon as the processed signal level drops below the level specified with this knob. - -The Controls button opens a dialog for editing the effect's parameters. - -Right clicking will bring up a context menu where you can change the order in which the effects are processed or delete an effect altogether. - - Move &up 위로 이동(&U) @@ -1397,239 +1314,155 @@ Right clicking will bring up a context menu where you can change the order in wh EnvelopeAndLfoParameters - Predelay - + Env pre-delay + - Attack - + Env attack + - Hold - + Env hold + - Decay - + Env decay + - Sustain - + Env sustain + - Release - + Env release + - Modulation - 변조 + Env mod amount + - LFO Predelay - + LFO pre-delay + - LFO Attack - + LFO attack + - LFO speed - + LFO frequency + - LFO Modulation - + LFO mod amount + - LFO Wave Shape - LFO 파형 + LFO wave shape + - Freq x 100 - + LFO frequency x 100 + - Modulate Env-Amount - + Modulate env amount + EnvelopeAndLfoView DEL - - - - Predelay: - - - - Use this knob for setting predelay of the current envelope. The bigger this value the longer the time before start of actual envelope. - + ATT - + Attack: - - - - Use this knob for setting attack-time of the current envelope. The bigger this value the longer the envelope needs to increase to attack-level. Choose a small value for instruments like pianos and a big value for strings. - + HOLD - + Hold: - - - - Use this knob for setting hold-time of the current envelope. The bigger this value the longer the envelope holds attack-level before it begins to decrease to sustain-level. - + DEC - 감쇄 + 감쇠 Decay: - 감쇄: - - - Use this knob for setting decay-time of the current envelope. The bigger this value the longer the envelope needs to decrease from attack-level to sustain-level. Choose a small value for instruments like pianos. - + 감쇠: SUST - + Sustain: - - - - Use this knob for setting sustain-level of the current envelope. The bigger this value the higher the level on which the envelope stays before going down to zero. - + REL - + Release: - - - - Use this knob for setting release-time of the current envelope. The bigger this value the longer the envelope needs to decrease from sustain-level to zero. Choose a big value for soft instruments like strings. - + AMT - + Modulation amount: - - - - Use this knob for setting modulation amount of the current envelope. The bigger this value the more the according size (e.g. volume or cutoff-frequency) will be influenced by this envelope. - - - - LFO predelay: - - - - Use this knob for setting predelay-time of the current LFO. The bigger this value the the time until the LFO starts to oscillate. - - - - LFO- attack: - - - - Use this knob for setting attack-time of the current LFO. The bigger this value the longer the LFO needs to increase its amplitude to maximum. - + SPD - - - - LFO speed: - LFO 속도: - - - Use this knob for setting speed of the current LFO. The bigger this value the faster the LFO oscillates and the faster will be your effect. - 이 노브를 사용하여 LFO의 속도를 설정합니다. 값이 클수록 LFO 진동이 빨라지게 됩니다. - - - Use this knob for setting modulation amount of the current LFO. The bigger this value the more the selected size (e.g. volume or cutoff-frequency) will be influenced by this LFO. - - - - Click here for a sine-wave. - 클릭하여 사인파를 선택합니다. - - - Click here for a triangle-wave. - 클릭하여 삼각파를 선택합니다. - - - Click here for a saw-wave for current. - 클릭하여 톱니파를 선택합니다. - - - Click here for a square-wave. - 클릭하여 사각파를 선택합니다. - - - Click here for a user-defined wave. Afterwards, drag an according sample-file onto the LFO graph. - + 속도 FREQ x 100 주파수 x 100 - - Click here if the frequency of this LFO should be multiplied by 100. - - - - multiply LFO-frequency by 100 - - - - MODULATE ENV-AMOUNT - - - - Click here to make the envelope-amount controlled by this LFO. - - - - control envelope-amount by this LFO - - ms/LFO: - + ms/LFO: Hint - + - Drag a sample from somewhere and drop it in this window. - + Pre-delay: + - Click here for random wave. - 클릭하여 무작위 파형을 선택합니다. + Frequency: + 주파수: + + + Multiply LFO frequency by 100 + + + + MODULATE ENV AMOUNT + + + + Control envelope amount by this LFO + + + + Drag and drop a sample into this window. + @@ -1642,157 +1475,117 @@ Right clicking will bring up a context menu where you can change the order in wh Output gain 출력 이득 - - Low shelf gain - - Peak 1 gain - + 피크 1 이득 Peak 2 gain - + 피크 2 이득 Peak 3 gain - + 피크 3 이득 Peak 4 gain - - - - High Shelf gain - + 피크 4 이득 HP res - - - - Low Shelf res - + 고역 필터 공명 Peak 1 BW - + 피크 1 대역폭 Peak 2 BW - + 피크 2 대역폭 Peak 3 BW - + 피크 3 대역폭 Peak 4 BW - - - - High Shelf res - + 피크 4 대역폭 LP res - + 저역 필터 공명 HP freq - - - - Low Shelf freq - + 고역 필터 주파수 Peak 1 freq - + 피크 1 주파수 Peak 2 freq - + 피크 2 주파수 Peak 3 freq - + 피크 3 주파수 Peak 4 freq - - - - High shelf freq - + 피크 4 주파수 LP freq - + 저역 필터 주파수 HP active - - - - Low shelf active - + Peak 1 active - + 피크 1 활성화 Peak 2 active - + 피크 2 활성화 Peak 3 active - + 피크 3 활성화 Peak 4 active - - - - High shelf active - + 피크 4 활성화 LP active - + LP 12 - + LP 12 LP 24 - + LP 24 LP 48 - + LP 48 HP 12 - + HP 12 HP 24 - + HP 24 HP 48 - - - - low pass type - - - - high pass type - + HP 48 Analyse IN @@ -1802,91 +1595,131 @@ Right clicking will bring up a context menu where you can change the order in wh Analyse OUT 출력 신호 분석 + + Low-shelf gain + + + + High-shelf gain + + + + Low-shelf res + + + + High-shelf res + + + + Low-shelf freq + + + + High-shelf freq + + + + Low-shelf active + + + + High-shelf active + + + + Low-pass type + + + + High-pass type + + EqControlsDialog HP - - - - Low Shelf - + Peak 1 - + 피크 1 Peak 2 - + 피크 2 Peak 3 - + 피크 3 Peak 4 - - - - High Shelf - + 피크 4 LP - - - - In Gain - + Gain 이득 - Out Gain - 출력 이득 + Bandwidth: + 대역폭: - Bandwidth: - + Octave + 옥타브 Resonance : - 공명: + 공명 : Frequency: 주파수: - lp grp - + Low-shelf + - hp grp - + High-shelf + - Octave - 옥타브 + Input gain + 입력 이득 + + + Output gain + 출력 이득 + + + LP group + + + + HP group + EqHandle Reso: - 공명: + 공명: BW: - 대역폭: + 대역폭: Freq: - 주파수: + 주파수: @@ -1895,18 +1728,10 @@ Right clicking will bring up a context menu where you can change the order in wh Export project 프로젝트 내보내기 - - Output - 출력 - File format: 파일 형식: - - Samplerate: - 샘플 레이트: - 44100 Hz 44100 Hz @@ -1927,6 +1752,18 @@ Right clicking will bring up a context menu where you can change the order in wh 192000 Hz 192000 Hz + + Stereo mode: + 스테레오 모드: + + + Stereo + 스테레오 + + + Mono + 모노 + Bitrate: 비트 레이트: @@ -1956,16 +1793,8 @@ Right clicking will bring up a context menu where you can change the order in wh 320 KBit/s - Depth: - - - - 16 Bit Integer - 16비트 정수 - - - 32 Bit Float - 32비트 실수 + Use variable bitrate + 가변 비트레이트 사용 Quality settings @@ -1975,26 +1804,6 @@ Right clicking will bring up a context menu where you can change the order in wh Interpolation: 보간법: - - Zero Order Hold - - - - Sinc Fastest - - - - Sinc Medium (recommended) - - - - Sinc Best (very slow!) - - - - Oversampling (use with care!): - - 1x (None) 1x (사용하지 않음) @@ -2011,6 +1820,10 @@ Right clicking will bring up a context menu where you can change the order in wh 8x 8x + + Export between loop markers + 반복 마커 사이 구간만 내보내기 + Start 시작 @@ -2019,18 +1832,16 @@ Right clicking will bring up a context menu where you can change the order in wh Cancel 취소 - - Export as loop (remove end silence) - 루프 곡처럼 내보내기 (후반부 여백 제거) - - - Export between loop markers - 반복 마커 사이 구간만 내보내기 - Could not open file 파일을 열 수 없음 + + Could not open file %1 for writing. +Please make sure you have write permission to the file and the directory containing the file and try again! + 파일 %1을(를) 쓰기 위하여 열 수 없습니다. +경로에 파일이 존재하고 파일에 쓸 수 있는 권한이 있는지 확인 후 다시 시도하시기 바랍니다! + Export project to %1 %1(으)로 프로젝트 내보내기 @@ -2048,93 +1859,76 @@ Right clicking will bring up a context menu where you can change the order in wh 렌더링: %1% - Could not open file %1 for writing. -Please make sure you have write permission to the file and the directory containing the file and try again! - 파일 %1을(를) 쓰기 위하여 열 수 없습니다. -경로에 파일이 존재하고 파일에 쓸 수 있는 권한이 있는지 확인 후 다시 시도하시기 바랍니다! + Compression level: + - 24 Bit Integer + Export as loop (remove extra bar) + 루프 곡처럼 내보내기 (후반부 여백 제거) + + + Render Looped Section: + + + + time(s) + + + + File format settings + + + + Sampling rate: + + + + Bit depth: + + + + 16 Bit integer + 16비트 정수 + + + 24 Bit integer 24비트 정수 - Use variable bitrate - 가변 비트레이트 사용 + 32 Bit float + 32비트 실수 - Stereo mode: - + Joint stereo + - Stereo - 스테레오 + Zero order hold + - Joint Stereo - + Sinc worst (fastest) + - Mono - 모노 + Sinc medium (recommended) + - Compression level: - + Sinc best (slowest) + - (fastest) - + Oversampling: + - (default) - + ( Fastest - biggest ) + - (smallest) - - - - - Expressive - - Selected graph - - - - A1 - - - - A2 - - - - A3 - - - - W1 smoothing - - - - W2 smoothing - - - - W3 smoothing - - - - PAN1 - - - - PAN2 - - - - REL TRANS - + ( Slowest - smallest ) + @@ -2143,6 +1937,10 @@ Please make sure you have write permission to the file and the directory contain Please enter a new value between %1 and %2: %1부터 %2까지의 값을 입력하세요: + + Set value + 값 설정 + FileBrowser @@ -2152,18 +1950,22 @@ Please make sure you have write permission to the file and the directory contain Search - + 검색 Refresh list - + 목록 새로고침 FileBrowserTreeWidget Send to active instrument-track - + 활성화된 악기 트랙에서 열기 + + + Open in new instrument-track/Song Editor + 새로운 악기 트랙이나 노래 편집기에서 열기 Open in new instrument-track/B+B Editor @@ -2175,15 +1977,7 @@ Please make sure you have write permission to the file and the directory contain Please wait, loading sample for preview... - - - - --- Factory files --- - - - - Open in new instrument-track/Song Editor - 새로운 악기 트랙이나 노래 편집기에서 열기 + 미리보기를 위하여 샘플을 로딩하는 중입니다. 잠시 기다려 주세요... Error @@ -2191,30 +1985,26 @@ Please make sure you have write permission to the file and the directory contain does not appear to be a valid - + file 파일 + + --- Factory files --- + + FlangerControls - - Delay Samples - - - - Lfo Frequency - LFO 주파수 - Seconds Regen - + Noise @@ -2224,40 +2014,40 @@ Please make sure you have write permission to the file and the directory contain Invert 파형 반전 + + Delay samples + + + + LFO frequency + LFO 주파수 + FlangerControlsDialog - - Delay Time: - - - - Feedback Amount: - - - - White Noise Amount: - - DELAY - + 지연 RATE - + + + + Period: + AMNT - + Amount: - + FDBK - + 피드백 NOISE @@ -2268,30 +2058,265 @@ Please make sure you have write permission to the file and the directory contain 파형 반전 - Period: - + Delay time: + + + + Feedback amount: + + + + White noise amount: + + + + + FreeBoyInstrument + + Sweep time + + + + Sweep direction + + + + Channel 1 volume + + + + Volume sweep direction + + + + Length of each step in sweep + + + + Channel 2 volume + + + + Channel 3 volume + + + + Channel 4 volume + + + + Shift Register width + + + + Channel 1 to SO2 (Left) + + + + Channel 2 to SO2 (Left) + + + + Channel 3 to SO2 (Left) + + + + Channel 4 to SO2 (Left) + + + + Channel 1 to SO1 (Right) + + + + Channel 2 to SO1 (Right) + + + + Channel 3 to SO1 (Right) + + + + Channel 4 to SO1 (Right) + + + + Treble + + + + Bass + + + + Sweep rate shift amount + + + + Wave pattern duty cycle + + + + Right output level + + + + Left output level + + + + + FreeBoyInstrumentView + + Length of each step in sweep: + + + + Length of each step in sweep + + + + Treble: + + + + Treble + + + + Bass: + + + + Bass + + + + Sweep time: + + + + Sweep time + + + + Sweep rate shift amount: + + + + Sweep rate shift amount + + + + Wave pattern duty cycle: + + + + Wave pattern duty cycle + + + + Square channel 1 volume: + + + + Square channel 1 volume + + + + Square channel 2 volume: + + + + Square channel 2 volume + + + + Wave pattern channel volume: + + + + Wave pattern channel volume + + + + Noise channel volume: + + + + Noise channel volume + + + + SO1 volume (Right): + + + + SO1 volume (Right) + + + + SO2 volume (Left): + + + + SO2 volume (Left) + + + + Sweep direction + + + + Volume sweep direction + + + + Shift register width + + + + Channel 1 to SO1 (Right) + + + + Channel 2 to SO1 (Right) + + + + Channel 3 to SO1 (Right) + + + + Channel 4 to SO1 (Right) + + + + Channel 1 to SO2 (Left) + + + + Channel 2 to SO2 (Left) + + + + Channel 3 to SO2 (Left) + + + + Channel 4 to SO2 (Left) + + + + Wave pattern graph + FxLine Channel send amount - - - - The FX channel receives input from one or more instrument tracks. - It in turn can be routed to multiple other FX channels. LMMS automatically takes care of preventing infinite loops for you and doesn't allow making a connection that would result in an infinite loop. - -In order to route the channel to another channel, select the FX channel and click on the "send" button on the channel you want to send to. The knob under the send button controls the level of signal that is sent to the channel. - -You can remove and move FX channels in the context menu, which is accessed by right-clicking the FX channel. - - FX 채널은 한 개 이상의 악기 트랙으로부터 사운드를 입력받습니다. -한 채널에서 여러 다른 채널로 사운드를 보낼 수 있습니다. LMMS는 FX 채널 간 무한 루프를 생성하는 것을 자동으로 방지합니다. -한 채널의 출력을 다른 채널로 보내려면 출력을 내보낼 FX 채널을 선택한 뒤 대상 채널의 "send" 버튼을 선택하시기 바랍니다. "send" 버튼 아래에 있는 노브를 통하여 보내질 신호의 레벨을 조절할 수 있습니다. - -FX 채널을 오른쪽 클릭하여 나오는 컨텍스트 메뉴에서 채널을 제거하거나 이동할 수 있습니다. - + Move &left @@ -2314,6 +2339,17 @@ FX 채널을 오른쪽 클릭하여 나오는 컨텍스트 메뉴에서 채널 사용하지 않는 채널 제거(&U) + + FxLineLcdSpinBox + + Assign to: + 채널 할당: + + + New FX Channel + 새 FX 채널 + + FxMixer @@ -2326,7 +2362,7 @@ FX 채널을 오른쪽 클릭하여 나오는 컨텍스트 메뉴에서 채널 Volume - 볼륨 + 음량 Mute @@ -2388,42 +2424,6 @@ FX 채널을 오른쪽 클릭하여 나오는 컨텍스트 메뉴에서 채널 GigInstrumentView - - Open other GIG file - 다른 GIG 파일 열기 - - - Click here to open another GIG file - 클릭하여 다른 GIG 파일 열기 - - - Choose the patch - 패치 선택 - - - Click here to change which patch of the GIG file to use - - - - Change which instrument of the GIG file is being played - - - - Which GIG file is currently being used - - - - Which patch of the GIG file is currently being used - - - - Gain - 이득 - - - Factor to multiply samples by - - Open GIG file GIG 파일 열기 @@ -2432,6 +2432,14 @@ FX 채널을 오른쪽 클릭하여 나오는 컨텍스트 메뉴에서 채널 GIG Files (*.gig) GIG 파일 (*.gig) + + Choose patch + + + + Gain: + 이득: + GuiApplication @@ -2490,6 +2498,18 @@ FX 채널을 오른쪽 클릭하여 나오는 컨텍스트 메뉴에서 채널 Arpeggio range 아르페지오 범위 + + Cycle steps + + + + Skip rate + + + + Miss rate + + Arpeggio time 아르페지오 시간 @@ -2508,15 +2528,19 @@ FX 채널을 오른쪽 클릭하여 나오는 컨텍스트 메뉴에서 채널 Up - + 위로 Down - 아래 + 아래로 Up and down - 위와 아래 + 위 다음 아래 + + + Down and up + 아래 다음 위 Random @@ -2524,7 +2548,7 @@ FX 채널을 오른쪽 클릭하여 나오는 컨텍스트 메뉴에서 채널 Free - + 자유 Sort @@ -2534,22 +2558,6 @@ FX 채널을 오른쪽 클릭하여 나오는 컨텍스트 메뉴에서 채널 Sync 동기화 - - Down and up - - - - Skip rate - - - - Miss rate - - - - Cycle steps - - InstrumentFunctionArpeggioView @@ -2557,10 +2565,6 @@ FX 채널을 오른쪽 클릭하여 나오는 컨텍스트 메뉴에서 채널 ARPEGGIO 아르페지오 - - An arpeggio is a method playing (especially plucked) instruments, which makes the music much livelier. The strings of such instruments (e.g. harps) are plucked like chords. The only difference is that this is done in a sequential order, so the notes are not played at the same time. Typical arpeggios are major or minor triads, but there are a lot of other possible chords, you can select. - - RANGE 범위 @@ -2574,8 +2578,36 @@ FX 채널을 오른쪽 클릭하여 나오는 컨텍스트 메뉴에서 채널 옥타브 - Use this knob for setting the arpeggio range in octaves. The selected arpeggio will be played within specified number of octaves. - 이 노브를 사용하여 아르페지오 범위를 옥타브 단위로 설정합니다. 아르페지오는 설정된 옥타브 범위 내에서 재생됩니다. + CYCLE + + + + Cycle notes: + + + + note(s) + + + + SKIP + + + + Skip rate: + + + + % + % + + + MISS + + + + Miss rate: + TIME @@ -2589,10 +2621,6 @@ FX 채널을 오른쪽 클릭하여 나오는 컨텍스트 메뉴에서 채널 ms ms - - Use this knob for setting the arpeggio time in milliseconds. The arpeggio time specifies how long each arpeggio-tone should be played. - 이 노브를 사용하여 아르페지오 시간을 밀리초 단위로 지정합니다. 아르페지오 시간은 각각의 아르페지오 음이 재생되는 길이를 결정합니다. - GATE 게이트 @@ -2601,14 +2629,6 @@ FX 채널을 오른쪽 클릭하여 나오는 컨텍스트 메뉴에서 채널 Arpeggio gate: 아르페지오 게이트: - - % - % - - - Use this knob for setting the arpeggio gate. The arpeggio gate specifies the percent of a whole arpeggio-tone that should be played. With this you can make cool staccato arpeggios. - - Chord: 코드: @@ -2621,46 +2641,6 @@ FX 채널을 오른쪽 클릭하여 나오는 컨텍스트 메뉴에서 채널 Mode: 모드: - - SKIP - - - - Skip rate: - - - - The skip function will make the arpeggiator pause one step randomly. From its start in full counter clockwise position and no effect it will gradually progress to full amnesia at maximum setting. - - - - MISS - - - - Miss rate: - - - - The miss function will make the arpeggiator miss the intended note. - - - - CYCLE - - - - Cycle notes: - - - - note(s) - - - - Jumps over n steps in the arpeggio and cycles around if we're over the note range. If the total note range is evenly divisible by the number of steps jumped over you will get stuck in a shorter arpeggio or even on one note. - - InstrumentFunctionNoteStacking @@ -2670,267 +2650,267 @@ FX 채널을 오른쪽 클릭하여 나오는 컨텍스트 메뉴에서 채널 Major - + Majb5 - + minor - + minb5 - + sus2 - + sus4 - + aug - + augsus4 - + tri - + 6 - + 6 6sus4 - + 6sus4 6add9 - + 6add9 m6 - + m6add9 - + 7 - + 7 7sus4 - + 7sus4 7#5 - + 7#5 7b5 - + 7b5 7#9 - + 7#9 7b9 - + 7b9 7#5#9 - + 7#5#9 7#5b9 - + 7#5b9 7b5b9 - + 7b5b9 7add11 - + 7add11 7add13 - + 7add13 7#11 - + 7#11 Maj7 - + Maj7b5 - + Maj7#5 - + Maj7#11 - + Maj7add13 - + m7 - + m7b5 - + m7b9 - + m7add11 - + m7add13 - + m-Maj7 - + m-Maj7add11 - + m-Maj7add13 - + 9 - + 9 9sus4 - + 9sus4 add9 - + add9 9#5 - + 9#5 9b5 - + 9b5 9#11 - + 9#11 9b13 - + 9b13 Maj9 - + Maj9sus4 - + Maj9#5 - + Maj9#11 - + m9 - + madd9 - + m9b5 - + m9-Maj7 - + 11 - + 11 11b9 - + 11b9 Maj11 - + m11 - + m-Maj11 - + 13 - + 13 13#9 - + 13#9 13b9 - + 13b9 13b5b9 - + 13b5b9 Maj13 - + m13 - + m-Maj13 - + Harmonic minor @@ -2942,119 +2922,127 @@ FX 채널을 오른쪽 클릭하여 나오는 컨텍스트 메뉴에서 채널 Whole tone - + Diminished - + Major pentatonic - + Minor pentatonic - + Jap in sen - + Major bebop - + Dominant bebop - + Blues - + Arabic - + Enigmatic - + Neopolitan - + Neopolitan minor - + Hungarian minor - + Dorian - + - Phrygolydian - + Phrygian + Lydian - + Mixolydian - + Aeolian - + Locrian - - - - Chords - - - - Chord type - - - - Chord range - + Minor - + Chromatic - + Half-Whole Diminished - + 5 - + 5 Phrygian dominant - + Persian - + + + + Chords + 코드 + + + Chord type + 코드 종류 + + + Chord range + 코드 범위 InstrumentFunctionNoteStackingView + + STACKING + 코드 쌓기 + + + Chord: + 코드: + RANGE 범위 @@ -3067,18 +3055,6 @@ FX 채널을 오른쪽 클릭하여 나오는 컨텍스트 메뉴에서 채널 octave(s) 옥타브 - - Use this knob for setting the chord range in octaves. The selected chord will be played within specified number of octaves. - 이 노브를 사용하여 코드 범위를 옥타브 단위로 설정합니다. 코드는 설정된 옥타브만큼 재생됩니다. - - - STACKING - - - - Chord: - 코드: - InstrumentMidiIOView @@ -3102,29 +3078,29 @@ FX 채널을 오른쪽 클릭하여 나오는 컨텍스트 메뉴에서 채널 PROGRAM 프로그램 + + NOTE + + MIDI devices to receive MIDI events from - + MIDI devices to send MIDI events to - - - - NOTE - + CUSTOM BASE VELOCITY - - - - Specify the velocity normalization base for MIDI-based instruments at 100% note velocity - + 사용자 지정 기준 벨로시티 BASE VELOCITY - + 기준 벨로시티 + + + Specify the velocity normalization base for MIDI-based instruments at 100% note velocity. + @@ -3134,7 +3110,7 @@ FX 채널을 오른쪽 클릭하여 나오는 컨텍스트 메뉴에서 채널 마스터 피치 - Enables the use of Master Pitch + Enables the use of master pitch 마스터 피치 사용 @@ -3142,11 +3118,11 @@ FX 채널을 오른쪽 클릭하여 나오는 컨텍스트 메뉴에서 채널 InstrumentSoundShaping VOLUME - 볼륨 + 음량 Volume - 볼륨 + 음량 CUTOFF @@ -3176,93 +3152,93 @@ FX 채널을 오른쪽 클릭하여 나오는 컨텍스트 메뉴에서 채널 Q/Resonance Q/공명 - - LowPass - - - - HiPass - - - - BandPass csg - - - - BandPass czpg - - Notch - - - - Allpass - + 노치 Moog - - - - 2x LowPass - - - - RC LowPass 12dB - - - - RC BandPass 12dB - - - - RC HighPass 12dB - - - - RC LowPass 24dB - - - - RC BandPass 24dB - - - - RC HighPass 24dB - - - - Vocal Formant Filter - + Moog 2x Moog - - - - SV LowPass - - - - SV BandPass - - - - SV HighPass - + 2x Moog SV Notch - + SV 노치 Fast Formant - + Tripole - + + + + Low-pass + + + + Hi-pass + + + + Band-pass csg + + + + Band-pass czpg + + + + All-pass + + + + 2x Low-pass + + + + RC Low-pass 12 dB/oct + + + + RC Band-pass 12 dB/oct + + + + RC High-pass 12 dB/oct + + + + RC Low-pass 24 dB/oct + + + + RC Band-pass 24 dB/oct + + + + RC High-pass 24 dB/oct + + + + Vocal Formant + + + + SV Low-pass + + + + SV Band-pass + + + + SV High-pass + @@ -3271,60 +3247,52 @@ FX 채널을 오른쪽 클릭하여 나오는 컨텍스트 메뉴에서 채널 TARGET 대상 - - These tabs contain envelopes. They're very important for modifying a sound, in that they are almost always necessary for substractive synthesis. For example if you have a volume envelope, you can set when the sound should have a specific volume. If you want to create some soft strings then your sound has to fade in and out very softly. This can be done by setting large attack and release times. It's the same for other envelope targets like panning, cutoff frequency for the used filter and so on. Just monkey around with it! You can really make cool sounds out of a saw-wave with just some envelopes...! - - FILTER 필터 - - Here you can select the built-in filter you want to use for this instrument-track. Filters are very important for changing the characteristics of a sound. - - - - Hz - Hz - - - Use this knob for setting the cutoff frequency for the selected filter. The cutoff frequency specifies the frequency for cutting the signal by a filter. For example a lowpass-filter cuts all frequencies above the cutoff frequency. A highpass-filter cuts all frequencies below cutoff frequency, and so on... - - - - RESO - 공명 - - - Resonance: - 공명: - - - Use this knob for setting Q/Resonance for the selected filter. Q/Resonance tells the filter how much it should amplify frequencies near Cutoff-frequency. - - FREQ 주파수 - cutoff frequency: - 차단 주파수: + Hz + Hz Envelopes, LFOs and filters are not supported by the current instrument. 이 악기는 엔벨로프, LFO, 필터를 지원하지 않습니다. + + Cutoff frequency: + 차단 주파수: + + + Q/RESO + Q/공명 + + + Q/Resonance: + Q/공명: + InstrumentTrack + + With this knob you can set the volume of the opened channel. + 이 노브를 이용하여 트랙의 음량을 조절할 수 있습니다. + unnamed_track 이름 없는 트랙 + + Base note + 기준 음 + Volume - 볼륨 + 음량 Panning @@ -3334,6 +3302,10 @@ FX 채널을 오른쪽 클릭하여 나오는 컨텍스트 메뉴에서 채널 Pitch 피치 + + Pitch range + 피치 범위 + FX channel FX 채널 @@ -3343,19 +3315,7 @@ FX 채널을 오른쪽 클릭하여 나오는 컨텍스트 메뉴에서 채널 기본 프리셋 - With this knob you can set the volume of the opened channel. - 이 노브를 이용하여 트랙의 볼륨을 조절할 수 있습니다. - - - Base note - - - - Pitch range - 피치 범위 - - - Master Pitch + Master pitch 마스터 피치 @@ -3363,15 +3323,15 @@ FX 채널을 오른쪽 클릭하여 나오는 컨텍스트 메뉴에서 채널 InstrumentTrackView Volume - 볼륨 + 음량 Volume: - 볼륨: + 음량: VOL - 볼륨 + 음량 Panning @@ -3387,7 +3347,7 @@ FX 채널을 오른쪽 클릭하여 나오는 컨텍스트 메뉴에서 채널 MIDI - + MIDI Input @@ -3408,17 +3368,13 @@ FX 채널을 오른쪽 클릭하여 나오는 컨텍스트 메뉴에서 채널 GENERAL SETTINGS 일반 설정 - - Instrument volume - 악기 볼륨 - Volume: - 볼륨: + 음량: VOL - 볼륨 + 음량 Panning @@ -3448,6 +3404,14 @@ FX 채널을 오른쪽 클릭하여 나오는 컨텍스트 메뉴에서 채널 PITCH 피치 + + Pitch range (semitones) + 피치 범위(반음) + + + RANGE + 범위 + FX channel FX 채널 @@ -3456,6 +3420,30 @@ FX 채널을 오른쪽 클릭하여 나오는 컨텍스트 메뉴에서 채널 FX FX + + Save current instrument track settings in a preset file + 프리셋 파일에 현재 악기 트랙의 설정 저장 + + + SAVE + 저장 + + + Envelope, filter & LFO + 엔벨로프, 필터 & LFO + + + Chord stacking & arpeggio + 코드 쌓기 & 아르페지오 + + + Effects + 효과 + + + Miscellaneous + 기타 + Save preset 프리셋 저장 @@ -3464,53 +3452,17 @@ FX 채널을 오른쪽 클릭하여 나오는 컨텍스트 메뉴에서 채널 XML preset file (*.xpf) XML 프리셋 파일 (*.xpf) - - Pitch range (semitones) - 피치 범위(반음) - - - RANGE - 범위 - - - Save current instrument track settings in a preset file - 프리셋 파일에 현재 악기 트랙의 설정 저장 - - - Click here, if you want to save current instrument track settings in a preset file. Later you can load this preset by double-clicking it in the preset-browser. - 클릭하여 설정을 프리셋 파일에 저장합니다. 나중에 프리셋 탐색기에서 더블클릭하여 다시 불러올 수 있습니다. - - - Use these controls to view and edit the next/previous track in the song editor. - 이 컨트롤을 이용하여 노래 편집기의 이전/다음 트랙을 보고 편집합니다. - - - SAVE - 저장 - - - Envelope, filter & LFO - - - - Chord stacking & arpeggio - - - - Effects - - - - MIDI settings - MIDI 설정 - - - Miscellaneous - - Plugin - + 플러그인 + + + Volume + 음량 + + + MIDI + MIDI @@ -3523,13 +3475,17 @@ FX 채널을 오른쪽 클릭하여 나오는 컨텍스트 메뉴에서 채널 Set logarithmic 로그스케일로 설정 + + Please enter a new value between -96.0 dBFS and 6.0 dBFS: + -96.0 dBFS부터 6.0 dBFS까지의 값을 입력하세요: + Please enter a new value between %1 and %2: %1부터 %2까지의 값을 입력하세요: - Please enter a new value between -96.0 dBFS and 6.0 dBFS: - -96.0 dBFS부터 6.0 dBFS까지의 값을 입력하세요: + Set value + 값 설정 @@ -3547,7 +3503,7 @@ FX 채널을 오른쪽 클릭하여 나오는 컨텍스트 메뉴에서 채널 Channel - 채널 + 채널 @@ -3560,10 +3516,6 @@ FX 채널을 오른쪽 클릭하여 나오는 컨텍스트 메뉴에서 채널 Value: 값: - - Sorry, no help available. - 죄송합니다. 도움말을 사용할 수 없습니다. - LadspaEffect @@ -3578,6 +3530,10 @@ FX 채널을 오른쪽 클릭하여 나오는 컨텍스트 메뉴에서 채널 Please enter a new value between %1 and %2: %1부터 %2까지의 값을 입력하세요: + + Set value + 값 설정 + LeftRightNav @@ -3606,15 +3562,15 @@ FX 채널을 오른쪽 클릭하여 나오는 컨텍스트 메뉴에서 채널 Base value - + 기준 값 Oscillator speed - + Oscillator amount - + Oscillator phase @@ -3626,7 +3582,7 @@ FX 채널을 오른쪽 클릭하여 나오는 컨텍스트 메뉴에서 채널 Frequency Multiplier - + @@ -3635,102 +3591,93 @@ FX 채널을 오른쪽 클릭하여 나오는 컨텍스트 메뉴에서 채널 LFO LFO - - LFO Controller - LFO 컨트롤러 - BASE - - - - Base amount: - - - - todo - - - - SPD - - - - LFO-speed: - - - - Use this knob for setting speed of the LFO. The bigger this value the faster the LFO oscillates and the faster the effect. - 이 노브를 사용하여 LFO의 속도를 설정합니다. 값이 클수록 LFO 진동이 빨라지게 됩니다. - - - Modulation amount: - - - - Use this knob for setting modulation amount of the LFO. The bigger this value, the more the connected control (e.g. volume or cutoff-frequency) will be influenced by the LFO. - - - - PHS - - - - Phase offset: - - - - degrees - - - - With this knob you can set the phase offset of the LFO. That means you can move the point within an oscillation where the oscillator begins to oscillate. For example if you have a sine-wave and have a phase-offset of 180 degrees the wave will first go down. It's the same with a square-wave. - - - - Click here for a sine-wave. - 클릭하여 사인파를 선택합니다. - - - Click here for a triangle-wave. - 클릭하여 삼각파를 선택합니다. - - - Click here for a saw-wave. - 클릭하여 톱니파를 선택합니다. - - - Click here for a square-wave. - 클릭하여 사각파를 선택합니다. - - - Click here for an exponential wave. - 클릭하여 지수형 파형을 선택합니다. - - - Click here for white-noise. - 클릭하여 화이트 노이즈를 선택합니다. - - - Click here for a user-defined shape. -Double click to pick a file. - 클릭하여 사용자 지정 파형을 선택합니다. -더블클릭하여 파일을 선택하세요. - - - Click here for a moog saw-wave. - + 기준 AMNT - + + + + Modulation amount: + + + + PHS + 위상 + + + Phase offset: + 위상: + + + Base: + + + + FREQ + 주파수 + + + LFO frequency: + + + + degrees + + + + Sine wave + 사인파 + + + Triangle wave + 삼각파 + + + Saw wave + 톱니파 + + + Square wave + 사각파 + + + Moog saw wave + Moog 톱니파 + + + Exponential wave + 지수형 파형 + + + White noise + 화이트 노이즈 + + + User-defined shape. +Double click to pick a file. + + + + Mutliply modulation frequency by 1 + + + + Mutliply modulation frequency by 100 + + + + Divide modulation frequency by 100 + LmmsCore Generating wavetables - + Initializing data structures @@ -3738,7 +3685,7 @@ Double click to pick a file. Opening audio and midi devices - 오디오 장치와 미디 장치를 여는 중 + 오디오 장치와 MIDI 장치를 여는 중 Launching mixer threads @@ -3747,14 +3694,112 @@ Double click to pick a file. MainWindow + + Configuration file + 설정 파일 + + + Error while parsing configuration file at line %1:%2: %3 + 설정 파일 분석 중 오류 발생 (행 %1:%2: %3) + + + Could not open file + 파일을 열 수 없음 + + + Could not open file %1 for writing. +Please make sure you have write permission to the file and the directory containing the file and try again! + 파일 %1을(를) 쓰기 위하여 열 수 없습니다. +경로에 파일이 존재하고 파일에 쓸 수 있는 권한이 있는지 확인 후 다시 시도하시기 바랍니다! + + + Project recovery + 프로젝트 복구 + + + There is a recovery file present. It looks like the last session did not end properly or another instance of LMMS is already running. Do you want to recover the project of this session? + 복구 파일이 존재합니다. 이전에 LMMS가 비정상 종료되었거나 여러 개의 LMMS 인스턴스가 동시에 실행 중인 것 같습니다. 복구 파일로부터 프로젝트를 복구하시겠습니까? + + + Recover + 복구 + + + Recover the file. Please don't run multiple instances of LMMS when you do this. + 파일을 복구합니다. 다른 LMMS 인스턴스가 실행 중이지 않은 상태에서 선택하시기 바랍니다. + + + Discard + 저장하지 않음 + + + Launch a default session and delete the restored files. This is not reversible. + 복구 파일을 삭제하고 기본 프로젝트를 불러옵니다. 이 동작은 되돌릴 수 없습니다. + + + Version %1 + 버전 %1 + + + Preparing plugin browser + 플러그인 탐색기 준비 + + + Preparing file browsers + 파일 탐색기 준비 + + + My Projects + 내 프로젝트 + + + My Samples + 내 샘플 + + + My Presets + 내 사전 설정 + + + My Home + 내 홈 디렉터리 + + + Root directory + 최상위 디렉토리 + + + Volumes + 음량 + + + My Computer + 내 컴퓨터 + + + Loading background artwork + 배경 아트워크를 불러오는 중 + + + &File + 파일(&F) + &New 새로 만들기(&N) + + New from template + 템플릿에서 새 프로젝트 생성 + &Open... 열기(&O)... + + &Recently Opened Projects + 최근에 사용한 프로젝트(&R) + &Save 저장(&S) @@ -3763,6 +3808,14 @@ Double click to pick a file. Save &As... 다른 이름으로 저장(&A)... + + Save as New &Version + 새로운 버전으로 저장(&V) + + + Save as default template + 기본 템플릿으로 저장 + Import... 가져오기... @@ -3771,6 +3824,14 @@ Double click to pick a file. E&xport... 내보내기(&X)... + + E&xport Tracks... + 트랙 내보내기(&X)... + + + Export &MIDI... + MIDI 내보내기(&M)... + &Quit 끝내기(&Q) @@ -3779,10 +3840,22 @@ Double click to pick a file. &Edit 편집(&E) + + Undo + 실행 취소 + + + Redo + 다시 실행 + Settings 설정 + + &View + 보기(&V) + &Tools 도구(&T) @@ -3792,12 +3865,12 @@ Double click to pick a file. 도움말(&H) - Help - 도움말 + Online Help + 온라인 도움말 - What's this? - + Help + 도움말 About @@ -3827,239 +3900,6 @@ Double click to pick a file. Export current project 현재 프로젝트 내보내기 - - Song Editor - 노래 편집기 - - - By pressing this button, you can show or hide the Song-Editor. With the help of the Song-Editor you can edit song-playlist and specify when which track should be played. You can also insert and move samples (e.g. rap samples) directly into the playlist. - - - - Beat+Bassline Editor - 비트/베이스 라인 편집기 - - - By pressing this button, you can show or hide the Beat+Bassline Editor. The Beat+Bassline Editor is needed for creating beats, and for opening, adding, and removing channels, and for cutting, copying and pasting beat and bassline-patterns, and for other things like that. - - - - Piano Roll - 피아노 롤 - - - Click here to show or hide the Piano-Roll. With the help of the Piano-Roll you can edit melodies in an easy way. - - - - Automation Editor - 오토메이션 편집기 - - - Click here to show or hide the Automation Editor. With the help of the Automation Editor you can edit dynamic values in an easy way. - - - - FX Mixer - FX 믹서 - - - Click here to show or hide the FX Mixer. The FX Mixer is a very powerful tool for managing effects for your song. You can insert effects into different effect-channels. - - - - Project Notes - 프로젝트 노트 - - - Click here to show or hide the project notes window. In this window you can put down your project notes. - - - - Controller Rack - 컨트롤러 랙 - - - Untitled - 제목 없음 - - - LMMS %1 - LMMS %1 - - - Project not saved - 프로젝트 저장되지 않음 - - - The current project was modified since last saving. Do you want to save it now? - 이 프로젝트는 마지막 저장 이후 수정되었습니다. 지금 저장하시겠습니까? - - - Help not available - 도움말 사용 불가 - - - Currently there's no help available in LMMS. -Please visit http://lmms.sf.net/wiki for documentation on LMMS. - - - - LMMS (*.mmp *.mmpz) - LMMS (*.mmp *.mmpz) - - - Version %1 - 버전 %1 - - - Configuration file - 설정 파일 - - - Error while parsing configuration file at line %1:%2: %3 - 설정 파일 분석 중 오류 발생 (행 %1:%2: %3) - - - Volumes - 볼륨 - - - Undo - 실행 취소 - - - Redo - 다시 실행 - - - My Projects - 내 프로젝트 - - - My Samples - 내 샘플 - - - My Presets - 내 사전 설정 - - - My Home - 내 홈 디렉터리 - - - My Computer - 내 컴퓨터 - - - &File - 파일(&F) - - - &Recently Opened Projects - 최근에 사용한 프로젝트(&R) - - - Save as New &Version - 새로운 버전으로 저장(&V) - - - E&xport Tracks... - 트랙 내보내기(&X)... - - - Online Help - 온라인 도움말 - - - What's This? - - - - Open Project - 프로젝트 열기 - - - Save Project - 프로젝트 저장 - - - Project recovery - 프로젝트 복구 - - - There is a recovery file present. It looks like the last session did not end properly or another instance of LMMS is already running. Do you want to recover the project of this session? - - - - Recover - 복구 - - - Recover the file. Please don't run multiple instances of LMMS when you do this. - - - - Discard - 저장하지 않음 - - - Launch a default session and delete the restored files. This is not reversible. - - - - Preparing plugin browser - 플러그인 탐색기 준비 - - - Preparing file browsers - 파일 탐색기 준비 - - - Root directory - 최상위 디렉토리 - - - Loading background artwork - - - - New from template - 템플릿에서 새 프로젝트 생성 - - - Save as default template - 기본 템플릿으로 저장 - - - &View - 보기(&V) - - - Toggle metronome - 메트로놈 토글 - - - Show/hide Song-Editor - 노래 편집기 보이기/숨기기 - - - Show/hide Beat+Bassline Editor - 비트/베이스 라인 편집기 보이기/숨기기 - - - Show/hide Piano-Roll - 피아노-롤 보이기/숨기기 - - - Show/hide Automation Editor - 오토메이션 편집기 보이기/숨기기 - - - Show/hide FX Mixer - FX 믹서 보이기/숨기기 - Show/hide project notes 프로젝트 노트 보이기/숨기기 @@ -4068,9 +3908,17 @@ Please visit http://lmms.sf.net/wiki for documentation on LMMS. Show/hide controller rack 컨트롤러 랙 보이기/숨기기 + + Untitled + 제목 없음 + Recover session. Please save your work! - + 복구 세션입니다. 프로젝트 파일을 저장해 주세요! + + + LMMS %1 + LMMS %1 Recovered project not saved @@ -4080,6 +3928,26 @@ Please visit http://lmms.sf.net/wiki for documentation on LMMS. This project was recovered from the previous session. It is currently unsaved and will be lost if you don't save it. Do you want to save it now? 이 프로젝트는 이전 세션으로부터 복구되었지만 아직 저장되지 않았습니다. 저장하지 않을 경우 지금까지의 작업을 잃게 될 것입니다. 지금 저장하시겠습니까? + + Project not saved + 프로젝트 저장되지 않음 + + + The current project was modified since last saving. Do you want to save it now? + 이 프로젝트는 마지막 저장 이후 수정되었습니다. 지금 저장하시겠습니까? + + + Open Project + 프로젝트 열기 + + + LMMS (*.mmp *.mmpz) + LMMS (*.mmp *.mmpz) + + + Save Project + 프로젝트 저장 + LMMS Project LMMS 프로젝트 @@ -4088,6 +3956,10 @@ Please visit http://lmms.sf.net/wiki for documentation on LMMS. LMMS Project Template LMMS 프로젝트 템플릿 + + Save project template + 프로젝트 템플릿 저장 + Overwrite default template? 기본 템플릿을 덮어쓰시겠습니까? @@ -4096,51 +3968,134 @@ Please visit http://lmms.sf.net/wiki for documentation on LMMS. This will overwrite your current default template. 이 작업은 현재의 기본 템플릿을 덮어씁니다. + + Help not available + 도움말 사용 불가 + + + Currently there's no help available in LMMS. +Please visit http://lmms.sf.net/wiki for documentation on LMMS. + + + + Song Editor + 노래 편집기 + + + Beat+Bassline Editor + 비트/베이스 라인 편집기 + + + Piano Roll + 피아노 롤 + + + Automation Editor + 오토메이션 편집기 + + + FX Mixer + FX 믹서 + + + Project Notes + 프로젝트 노트 + + + Controller Rack + 컨트롤러 랙 + + + Volume as dBFS + 음량을 dBFS 단위로 표시 + Smooth scroll 부드러운 스크롤 Enable note labels in piano roll - + 피아노 롤에 음표 라벨 표시 - Save project template - 프로젝트 템플릿 저장 + Metronome + 메트로놈 - Volume as dBFS - 볼륨을 dBFS 단위로 표시 + MIDI File (*.mid) + MIDI 파일(*.mid) - Could not open file - 파일을 열 수 없음 + untitled + 제목 없음 - Could not open file %1 for writing. -Please make sure you have write permission to the file and the directory containing the file and try again! - 파일 %1을(를) 쓰기 위하여 열 수 없습니다. -경로에 파일이 존재하고 파일에 쓸 수 있는 권한이 있는지 확인 후 다시 시도하시기 바랍니다! + Select file for project-export... + 프로젝트를 내보낼 파일 선택... - Export &MIDI... - + Select directory for writing exported tracks... + 내보낼 트랙 파일들을 저장할 경로 선택... + + + Save project + 프로젝트 저장 + + + Project saved + 프로젝트 저장됨 + + + The project %1 is now saved. + 프로젝트 %1이 저장되었습니다. + + + Project NOT saved. + 프로젝트가 저장되지 않았습니다. + + + The project %1 was not saved! + 프로젝트 %1이 저장되지 않았습니다! + + + Import file + 파일 가져오기 + + + MIDI sequences + MIDI 시퀀스 + + + Hydrogen projects + Hydrogen 프로젝트 + + + All file types + 모든 파일 MeterDialog Meter Numerator - + 박자표 분자 Meter Denominator - + 박자표 분모 TIME SIG 박자 + + Meter numerator + 박자표 분자 + + + Meter denominator + 박자표 분모 + MeterModel @@ -4170,18 +4125,18 @@ Please make sure you have write permission to the file and the directory contain Setup incomplete 설정 불완전 - - You do not have set up a default soundfont in the settings dialog (Edit->Settings). Therefore no sound will be played back after importing this MIDI file. You should download a General MIDI soundfont, specify it in settings dialog and try again. - - You did not compile LMMS with support for SoundFont2 player, which is used to add default sound to imported MIDI files. Therefore no sound will be played back after importing this MIDI file. - + LMMS가 SoundFont2 플레이어 지원 없이 컴파일되었습니다. MIDI 파일에서 가져온 트랙은 기본적으로 SoundFont2 플레이어로 재생되므로 MIDI 파일을 가져온 뒤 재생하면 아무 소리도 재생되지 않을 것입니다. Track 트랙 + + You have not set up a default soundfont in the settings dialog (Edit->Settings). Therefore no sound will be played back after importing this MIDI file. You should download a General MIDI soundfont, specify it in settings dialog and try again. + + MidiJack @@ -4222,25 +4177,25 @@ Please make sure you have write permission to the file and the directory contain Fixed output velocity 출력 벨로시티 고정값 + + Fixed output note + 출력 음높이 고정값 + Output MIDI program 출력 MIDI 프로그램 + + Base velocity + 기준 벨로시티 + Receive MIDI-events - + MIDI 이벤트 받기 Send MIDI-events - - - - Fixed output note - - - - Base velocity - + MIDI 이벤트 보내기 @@ -4252,385 +4207,13 @@ Please make sure you have write permission to the file and the directory contain MonstroInstrument - - Osc 1 Volume - 오실레이터 1 볼륨 - - - Osc 1 Panning - 오실레이터 1 패닝 - - - Osc 1 Coarse detune - - - - Osc 1 Fine detune left - - - - Osc 1 Fine detune right - - - - Osc 1 Stereo phase offset - - - - Osc 1 Pulse width - 오실레이터 1 펄스 폭 - - - Osc 1 Sync send on rise - - - - Osc 1 Sync send on fall - - - - Osc 2 Volume - 오실레이터 2 볼륨 - - - Osc 2 Panning - 오실레이터 2 패닝 - - - Osc 2 Coarse detune - - - - Osc 2 Fine detune left - - - - Osc 2 Fine detune right - - - - Osc 2 Stereo phase offset - - - - Osc 2 Waveform - 오실레이터 2 파형 - - - Osc 2 Sync Hard - - - - Osc 2 Sync Reverse - - - - Osc 3 Volume - 오실레이터 3 볼륨 - - - Osc 3 Panning - 오실레이터 3 패닝 - - - Osc 3 Coarse detune - - Osc 3 Stereo phase offset - - - - Osc 3 Sub-oscillator mix - - - - Osc 3 Waveform 1 - 오실레이터 3 파형 1 - - - Osc 3 Waveform 2 - 오실레이터 3 파형 2 - - - Osc 3 Sync Hard - - - - Osc 3 Sync Reverse - - - - LFO 1 Waveform - LFO 1 파형 - - - LFO 1 Attack - - - - LFO 1 Rate - - - - LFO 1 Phase - - - - LFO 2 Waveform - LFO 2 파형 - - - LFO 2 Attack - - - - LFO 2 Rate - - - - LFO 2 Phase - - - - Env 1 Pre-delay - - - - Env 1 Attack - - - - Env 1 Hold - - - - Env 1 Decay - - - - Env 1 Sustain - - - - Env 1 Release - - - - Env 1 Slope - - - - Env 2 Pre-delay - - - - Env 2 Attack - - - - Env 2 Hold - - - - Env 2 Decay - - - - Env 2 Sustain - - - - Env 2 Release - - - - Env 2 Slope - - - - Osc2-3 modulation - + Selected view - - - - Vol1-Env1 - - - - Vol1-Env2 - - - - Vol1-LFO1 - - - - Vol1-LFO2 - - - - Vol2-Env1 - - - - Vol2-Env2 - - - - Vol2-LFO1 - - - - Vol2-LFO2 - - - - Vol3-Env1 - - - - Vol3-Env2 - - - - Vol3-LFO1 - - - - Vol3-LFO2 - - - - Phs1-Env1 - - - - Phs1-Env2 - - - - Phs1-LFO1 - - - - Phs1-LFO2 - - - - Phs2-Env1 - - - - Phs2-Env2 - - - - Phs2-LFO1 - - - - Phs2-LFO2 - - - - Phs3-Env1 - - - - Phs3-Env2 - - - - Phs3-LFO1 - - - - Phs3-LFO2 - - - - Pit1-Env1 - - - - Pit1-Env2 - - - - Pit1-LFO1 - - - - Pit1-LFO2 - - - - Pit2-Env1 - - - - Pit2-Env2 - - - - Pit2-LFO1 - - - - Pit2-LFO2 - - - - Pit3-Env1 - - - - Pit3-Env2 - - - - Pit3-LFO1 - - - - Pit3-LFO2 - - - - PW1-Env1 - - - - PW1-Env2 - - - - PW1-LFO1 - - - - PW1-LFO2 - - - - Sub3-Env1 - - - - Sub3-Env2 - - - - Sub3-LFO1 - - - - Sub3-LFO2 - + Sine wave @@ -4638,35 +4221,35 @@ Please make sure you have write permission to the file and the directory contain Bandlimited Triangle wave - + 대역 제한 삼각파 Bandlimited Saw wave - + 대역 제한 톱니파 Bandlimited Ramp wave - + 대역 제한 역톱니파 Bandlimited Square wave - + 대역 제한 사각파 Bandlimited Moog saw wave - + 대역 제한 Moog 톱니파 Soft square wave - + Absolute sine wave - + Exponential wave - + 지수형 파형 White noise @@ -4690,7 +4273,7 @@ Please make sure you have write permission to the file and the directory contain Digital Moog saw wave - + Moog 톱니파 Triangle wave @@ -4702,7 +4285,7 @@ Please make sure you have write permission to the file and the directory contain Ramp wave - + 역톱니파 Square wave @@ -4710,11 +4293,11 @@ Please make sure you have write permission to the file and the directory contain Moog saw wave - + Moog 톱니파 Abs. sine wave - + Random @@ -4722,182 +4305,394 @@ Please make sure you have write permission to the file and the directory contain Random smooth - + + + + Osc 1 volume + 오실레이터 1 음량 + + + Osc 1 panning + 오실레이터 1 패닝 + + + Osc 1 coarse detune + + + + Osc 1 fine detune left + + + + Osc 1 fine detune right + + + + Osc 1 stereo phase offset + + + + Osc 1 pulse width + + + + Osc 1 sync send on rise + + + + Osc 1 sync send on fall + + + + Osc 2 volume + 오실레이터 2 음량 + + + Osc 2 panning + 오실레이터 2 패닝 + + + Osc 2 coarse detune + + + + Osc 2 fine detune left + + + + Osc 2 fine detune right + + + + Osc 2 stereo phase offset + + + + Osc 2 waveform + 오실레이터 2 파형 + + + Osc 2 sync hard + + + + Osc 2 sync reverse + + + + Osc 3 volume + 오실레이터 3 음량 + + + Osc 3 panning + 오실레이터 3 패닝 + + + Osc 3 coarse detune + + + + Osc 3 sub-oscillator mix + + + + Osc 3 waveform 1 + 오실레이터 3 파형 1 + + + Osc 3 waveform 2 + 오실레이터 3 파형 2 + + + Osc 3 sync hard + + + + Osc 3 Sync reverse + + + + LFO 1 waveform + + + + LFO 1 attack + + + + LFO 1 rate + + + + LFO 1 phase + + + + LFO 2 waveform + + + + LFO 2 attack + + + + LFO 2 rate + + + + LFO 2 phase + + + + Env 1 pre-delay + + + + Env 1 attack + + + + Env 1 hold + + + + Env 1 decay + + + + Env 1 sustain + + + + Env 1 release + + + + Env 1 slope + + + + Env 2 pre-delay + + + + Env 2 attack + + + + Env 2 hold + + + + Env 2 decay + + + + Env 2 sustain + + + + Env 2 release + + + + Env 2 slope + + + + Osc 2+3 modulation + + + + Osc 1 - Vol env 1 + + + + Osc 1 - Vol env 2 + + + + Osc 1 - Vol LFO 1 + + + + Osc 1 - Vol LFO 2 + + + + Osc 2 - Vol env 1 + + + + Osc 2 - Vol env 2 + + + + Osc 2 - Vol LFO 1 + + + + Osc 2 - Vol LFO 2 + + + + Osc 3 - Vol env 1 + + + + Osc 3 - Vol env 2 + + + + Osc 3 - Vol LFO 1 + + + + Osc 3 - Vol LFO 2 + + + + Osc 1 - Phs env 1 + + + + Osc 1 - Phs env 2 + + + + Osc 1 - Phs LFO 1 + + + + Osc 1 - Phs LFO 2 + + + + Osc 2 - Phs env 1 + + + + Osc 2 - Phs env 2 + + + + Osc 2 - Phs LFO 1 + + + + Osc 2 - Phs LFO 2 + + + + Osc 3 - Phs env 1 + + + + Osc 3 - Phs env 2 + + + + Osc 3 - Phs LFO 1 + + + + Osc 3 - Phs LFO 2 + + + + Osc 1 - Pit env 1 + + + + Osc 1 - Pit env 2 + + + + Osc 1 - Pit LFO 1 + + + + Osc 1 - Pit LFO 2 + + + + Osc 2 - Pit env 1 + + + + Osc 2 - Pit env 2 + + + + Osc 2 - Pit LFO 1 + + + + Osc 2 - Pit LFO 2 + + + + Osc 3 - Pit env 1 + + + + Osc 3 - Pit env 2 + + + + Osc 3 - Pit LFO 1 + + + + Osc 3 - Pit LFO 2 + + + + Osc 1 - PW env 1 + + + + Osc 1 - PW env 2 + + + + Osc 1 - PW LFO 1 + + + + Osc 1 - PW LFO 2 + + + + Osc 3 - Sub env 1 + + + + Osc 3 - Sub env 2 + + + + Osc 3 - Sub LFO 1 + + + + Osc 3 - Sub LFO 2 + MonstroView Operators view - - - - The Operators view contains all the operators. These include both audible operators (oscillators) and inaudible operators, or modulators: Low-frequency oscillators and Envelopes. - -Knobs and other widgets in the Operators view have their own what's this -texts, so you can get more specific help for them that way. - + Matrix view - - - - The Matrix view contains the modulation matrix. Here you can define the modulation relationships between the various operators: Each audible operator (oscillators 1-3) has 3-4 properties that can be modulated by any of the modulators. Using more modulations consumes more CPU power. - -The view is divided to modulation targets, grouped by the target oscillator. Available targets are volume, pitch, phase, pulse width and sub-osc ratio. Note: some targets are specific to one oscillator only. - -Each modulation target has 4 knobs, one for each modulator. By default the knobs are at 0, which means no modulation. Turning a knob to 1 causes that modulator to affect the modulation target as much as possible. Turning it to -1 does the same, but the modulation is inversed. - - - - Mix Osc2 with Osc3 - - - - Modulate amplitude of Osc3 with Osc2 - 오실레이터 2로 오실레이터 3의 진폭 변조 - - - Modulate frequency of Osc3 with Osc2 - 오실레이터 2로 오실레이터 3의 주파수 변조 - - - Modulate phase of Osc3 with Osc2 - 오실레이터 2로 오실레이터 3의 위상 변조 - - - The CRS knob changes the tuning of oscillator 1 in semitone steps. - - - - The CRS knob changes the tuning of oscillator 2 in semitone steps. - - - - The CRS knob changes the tuning of oscillator 3 in semitone steps. - - - - FTL and FTR change the finetuning of the oscillator for left and right channels respectively. These can add stereo-detuning to the oscillator which widens the stereo image and causes an illusion of space. - - - - The SPO knob modifies the difference in phase between left and right channels. Higher difference creates a wider stereo image. - - - - The PW knob controls the pulse width, also known as duty cycle, of oscillator 1. Oscillator 1 is a digital pulse wave oscillator, it doesn't produce bandlimited output, which means that you can use it as an audible oscillator but it will cause aliasing. You can also use it as an inaudible source of a sync signal, which can be used to synchronize oscillators 2 and 3. - - - - Send Sync on Rise: When enabled, the Sync signal is sent every time the state of oscillator 1 changes from low to high, ie. when the amplitude changes from -1 to 1. Oscillator 1's pitch, phase and pulse width may affect the timing of syncs, but its volume has no effect on them. Sync signals are sent independently for both left and right channels. - - - - Send Sync on Fall: When enabled, the Sync signal is sent every time the state of oscillator 1 changes from high to low, ie. when the amplitude changes from 1 to -1. Oscillator 1's pitch, phase and pulse width may affect the timing of syncs, but its volume has no effect on them. Sync signals are sent independently for both left and right channels. - - - - Hard sync: Every time the oscillator receives a sync signal from oscillator 1, its phase is reset to 0 + whatever its phase offset is. - - - - Reverse sync: Every time the oscillator receives a sync signal from oscillator 1, the amplitude of the oscillator gets inverted. - - - - Choose waveform for oscillator 2. - 오실레이터 2에 사용할 파형을 선택하세요. - - - Choose waveform for oscillator 3's first sub-osc. Oscillator 3 can smoothly interpolate between two different waveforms. - - - - Choose waveform for oscillator 3's second sub-osc. Oscillator 3 can smoothly interpolate between two different waveforms. - - - - The SUB knob changes the mixing ratio of the two sub-oscs of oscillator 3. Each sub-osc can be set to produce a different waveform, and oscillator 3 can smoothly interpolate between them. All incoming modulations to oscillator 3 are applied to both sub-oscs/waveforms in the exact same way. - - - - In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. - -Mix mode means no modulation: the outputs of the oscillators are simply mixed together. - - - - In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. - -AM means amplitude modulation: Oscillator 3's amplitude (volume) is modulated by oscillator 2. - - - - In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. - -FM means frequency modulation: Oscillator 3's frequency (pitch) is modulated by oscillator 2. The frequency modulation is implemented as phase modulation, which gives a more stable overall pitch than "pure" frequency modulation. - - - - In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. - -PM means phase modulation: Oscillator 3's phase is modulated by oscillator 2. It differs from frequency modulation in that the phase changes are not cumulative. - - - - Select the waveform for LFO 1. -"Random" and "Random smooth" are special waveforms: they produce random output, where the rate of the LFO controls how often the state of the LFO changes. The smooth version interpolates between these states with cosine interpolation. These random modes can be used to give "life" to your presets - add some of that analog unpredictability... - - - - Select the waveform for LFO 2. -"Random" and "Random smooth" are special waveforms: they produce random output, where the rate of the LFO controls how often the state of the LFO changes. The smooth version interpolates between these states with cosine interpolation. These random modes can be used to give "life" to your presets - add some of that analog unpredictability... - - - - Attack causes the LFO to come on gradually from the start of the note. - - - - Rate sets the speed of the LFO, measured in milliseconds per cycle. Can be synced to tempo. - - - - PHS controls the phase offset of the LFO. - - - - PRE, or pre-delay, delays the start of the envelope from the start of the note. 0 means no delay. - - - - ATT, or attack, controls how fast the envelope ramps up at start, measured in milliseconds. A value of 0 means instant. - - - - HOLD controls how long the envelope stays at peak after the attack phase. - - - - DEC, or decay, controls how fast the envelope falls off from its peak, measured in milliseconds it would take to go from peak to zero. The actual decay may be shorter if sustain is used. - - - - SUS, or sustain, controls the sustain level of the envelope. The decay phase will not go below this level as long as the note is held. - - - - REL, or release, controls how long the release is for the note, measured in how long it would take to fall from peak to zero. Actual release may be shorter, depending on at what phase the note is released. - - - - The slope knob controls the curve or shape of the envelope. A value of 0 creates straight rises and falls. Negative values create curves that start slowly, peak quickly and fall of slowly again. Positive values create curves that start and end quickly, and stay longer near the peaks. - + Volume - 볼륨 + 음량 Panning @@ -4905,27 +4700,19 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator Coarse detune - + semitones 반음 - - Finetune left - - cents 센트 - - Finetune right - - Stereo phase offset - + deg @@ -4937,35 +4724,35 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator Send sync on pulse rise - + Send sync on pulse fall - + Hard sync oscillator 2 - + Reverse sync oscillator 2 - + Sub-osc mix - + Hard sync oscillator 3 - + Reverse sync oscillator 3 - + Attack - + Rate @@ -4977,31 +4764,55 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator Pre-delay - + Hold - + Decay - + Sustain - + Release - + Slope - + Modulation amount - + + + + Fine tune left + + + + Fine tune right + + + + Mix osc 2 with osc 3 + + + + Modulate amplitude of osc 3 by osc 2 + + + + Modulate frequency of osc 3 by osc 2 + + + + Modulate phase of osc 3 by osc 2 + @@ -5012,129 +4823,133 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator Step length: - + Dry - - - - Dry Gain: - + Stages - - - - Lowpass stages: - + Swap inputs - + 좌우 입력 바꾸기 - Swap left and right input channel for reflections - + Dry gain: + + + + Low-pass stages: + + + + Swap left and right input channels for reflections + NesInstrument - - Channel 1 Coarse detune - - - - Channel 1 Volume - - - - Channel 1 Envelope length - - - - Channel 1 Duty cycle - - - - Channel 1 Sweep amount - - - - Channel 1 Sweep rate - - Channel 2 Coarse detune - + Channel 2 Volume - - - - Channel 2 Envelope length - - - - Channel 2 Duty cycle - - - - Channel 2 Sweep amount - - - - Channel 2 Sweep rate - - - - Channel 3 Coarse detune - - - - Channel 3 Volume - + Channel 4 Volume - - - - Channel 4 Envelope length - - - - Channel 4 Noise frequency - - - - Channel 4 Noise frequency sweep - + Master volume - 마스터 볼륨 + 마스터 음량 Vibrato 비브라토 + + Channel 1 coarse detune + + + + Channel 1 volume + + + + Channel 1 envelope length + + + + Channel 1 duty cycle + + + + Channel 1 sweep amount + + + + Channel 1 sweep rate + + + + Channel 2 envelope length + + + + Channel 2 duty cycle + + + + Channel 2 sweep amount + + + + Channel 2 sweep rate + + + + Channel 3 coarse detune + + + + Channel 3 volume + + + + Channel 4 volume + + + + Channel 4 envelope length + + + + Channel 4 noise frequency + + + + Channel 4 noise frequency sweep + + NesInstrumentView Volume - 볼륨 + 음량 Coarse detune - + Envelope length - + Enable channel 1 @@ -5146,35 +4961,35 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator Enable envelope 1 loop - + Enable sweep 1 - + Sweep amount - + Sweep rate - + 12.5% Duty cycle - + 25% Duty cycle - + 50% Duty cycle - + 75% Duty cycle - + Enable channel 2 @@ -5186,11 +5001,11 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator Enable envelope 2 loop - + Enable sweep 2 - + Enable channel 3 @@ -5198,11 +5013,11 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator Noise Frequency - + Frequency sweep - + Enable channel 4 @@ -5214,85 +5029,223 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator Enable envelope 4 loop - + Quantize noise frequency when using note frequency - + Use note frequency for noise - + Noise mode - - - - Master Volume - 마스터 볼륨 + Vibrato 비브라토 + + Master volume + 마스터 음량 + + + + OpulenzInstrument + + Patch + 패치 + + + Op 1 attack + + + + Op 1 decay + + + + Op 1 sustain + + + + Op 1 release + + + + Op 1 level + + + + Op 1 level scaling + + + + Op 1 frequency multiplier + + + + Op 1 feedback + + + + Op 1 key scaling rate + + + + Op 1 percussive envelope + + + + Op 1 tremolo + + + + Op 1 vibrato + + + + Op 1 waveform + + + + Op 2 attack + + + + Op 2 decay + + + + Op 2 sustain + + + + Op 2 release + + + + Op 2 level + + + + Op 2 level scaling + + + + Op 2 frequency multiplier + + + + Op 2 key scaling rate + + + + Op 2 percussive envelope + + + + Op 2 tremolo + + + + Op 2 vibrato + + + + Op 2 waveform + + + + FM + FM + + + Vibrato depth + + + + Tremolo depth + + + + + OpulenzInstrumentView + + Attack + + + + Decay + + + + Release + + + + Frequency multiplier + + OscillatorObject - - Osc %1 volume - - - - Osc %1 panning - - - - Osc %1 coarse detuning - - - - Osc %1 fine detuning left - - - - Osc %1 fine detuning right - - - - Osc %1 phase-offset - - - - Osc %1 stereo phase-detuning - - - - Osc %1 wave shape - - - - Modulation type %1 - - Osc %1 waveform 오실레이터 %1 파형 Osc %1 harmonic - + + + + Osc %1 volume + 오실레이터 %1 음량 + + + Osc %1 panning + 오실레이터 %1 패닝 + + + Osc %1 fine detuning left + + + + Osc %1 coarse detuning + + + + Osc %1 fine detuning right + + + + Osc %1 phase-offset + 오실레이터 %1 위상 + + + Osc %1 stereo phase-detuning + 오실레이터 %1 좌우 위상차 + + + Osc %1 wave shape + 오실레이터 %1 파형 + + + Modulation type %1 + 변조 유형 %1 PatchesDialog Qsynth: Channel Preset - + Bank selector - + Bank @@ -5300,7 +5253,7 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator Program selector - + Patch @@ -5321,14 +5274,6 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator PatmanView - - Open other patch - - - - Click here to open another patch-file. Loop and Tune settings are not reset. - - Loop 루프 @@ -5337,25 +5282,17 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator Loop mode 루프 모드 - - Here you can toggle the Loop mode. If enabled, PatMan will use the loop information available in the file. - - Tune - + Tune mode - - - - Here you can toggle the Tune mode. If enabled, PatMan will tune the sample to match the note's frequency. - + No file selected - + 파일이 선택되지 않음 Open patch file @@ -5365,6 +5302,10 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator Patch-Files (*.pat) 패치 파일 (*.pat) + + Open patch + + PatternView @@ -5386,37 +5327,41 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator Add steps - 단계 더하기 + Remove steps - 단계 제거 + Clone Steps - + + + + Set as ghost in piano-roll + PeakController Peak Controller - + 피크 컨트롤러 Peak Controller Bug - + 피크 컨트롤러 버그 Due to a bug in older version of LMMS, the peak controllers may not be connect properly. Please ensure that peak controllers are connected properly and re-save this file. Sorry for any inconvenience caused. - + 이전 버전 LMMS의 버그로 인해 피크 컨트롤러가 제대로 연결되지 않았을 수 있습니다. 피크 컨트롤러가 제대로 연결되었는지 확인 후 파일을 다시 저장해 주시기 바랍니다. 불편을 드려 죄송합니다. PeakControllerDialog PEAK - + LFO Controller @@ -5427,102 +5372,98 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator PeakControllerEffectControlDialog BASE - - - - Base amount: - - - - Modulation amount: - - - - Attack: - - - - Release: - + 기준 AMNT - + + + + Modulation amount: + MULT - - - - Amount Multiplicator: - + ATCK - + + + + Attack: + DCAY - + - Treshold: - + Release: + TRSH - + + + + Treshold: + + + + Base: + + + + Amount multiplicator: + + + + Mute output + 출력 음소거 + + + Absolute value + PeakControllerEffectControls Base value - + 기준 값 Modulation amount - - - - Mute output - + Attack - + Release - - - - Abs Value - 절댓값 - - - Amount Multiplicator - + Treshold - + + + + Mute output + 출력 음소거 + + + Absolute value + 절댓값 + + + Amount multiplicator + PianoRoll - - Please open a pattern by double-clicking on it! - 더블클릭하여 패턴을 열어주세요! - - - Last note - 마지막 박자 - - - Note lock - 박자 잠금 - Note Velocity 음표 벨로시티 @@ -5533,19 +5474,35 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator Mark/unmark current semitone - + 현재 반음 표시 + + + Mark/unmark all corresponding octave semitones + Mark current scale - + Mark current chord - + Unmark all - + 모두 표시 해제 + + + Select all notes on this key + 이 음의 음표 모두 선택 + + + Note lock + 박자 잠금 + + + Last note + 마지막 박자 No scale @@ -5571,18 +5528,14 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator Panning: center 패닝: 가운데 + + Please open a pattern by double-clicking on it! + 더블클릭하여 패턴을 열어주세요! + Please enter a new value between %1 and %2: %1부터 %2까지의 값을 입력하세요: - - Mark/unmark all corresponding octave semitones - - - - Select all notes on this key - 이 음의 음표 모두 선택 - PianoRollWindow @@ -5592,31 +5545,19 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator Record notes from MIDI-device/channel-piano - + Record notes from MIDI-device/channel-piano while playing song or BB track - + Stop playing of current pattern (Space) 현재 패턴 정지 (Space) - Click here to play the current pattern. This is useful while editing it. The pattern is automatically looped when its end is reached. - 클릭하여 현재 패턴을 재생합니다. 패턴은 자동으로 반복 재생됩니다. - - - Click here to record notes from a MIDI-device or the virtual test-piano of the according channel-window to the current pattern. When recording all notes you play will be written to this pattern and you can play and edit them afterwards. - - - - Click here to record notes from a MIDI-device or the virtual test-piano of the according channel-window to the current pattern. When recording all notes you play will be written to this pattern and you will hear the song or BB track in the background. - - - - Click here to stop playback of current pattern. - 현재 패턴의 재생을 정지하려면 여기를 클릭하세요. + Edit actions + 편집 동작 Draw mode (Shift+D) @@ -5631,72 +5572,12 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator 선택 모드 (Shift+S) - Detune mode (Shift+T) - 피치 조절 모드(Shift+T) + Pitch Bend mode (Shift+T) + - Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold %1 to temporarily go into select mode. - 여기를 클릭하면 그리기 모드가 활성화됩니다. 그리기 모드에서는 음표를 추가, 이동할 수 있으며 길이를 조절할 수도 있습니다. 이 모드는 대부분의 경우에 사용되는 기본 모드입니다. 'Shift+D' 키를 눌러 이 모드를 활성화할 수도 있습니다. 이 모드에서 %1키를 누르면 일시적으로 선택 모드로 전환됩니다. - - - Click here and erase mode will be activated. In this mode you can erase notes. You can also press 'Shift+E' on your keyboard to activate this mode. - - - - Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold %1 in draw mode to temporarily use select mode. - 여기를 클릭하면 선택 모드가 활성화됩니다. 선택 모드에서는 음표를 선택할 수 있습니다. 그리기 모드에서 %1키를 누르면 일시적으로 선택 모드로 전환됩니다. - - - Click here and detune mode will be activated. In this mode you can click a note to open its automation detuning. You can utilize this to slide notes from one to another. You can also press 'Shift+T' on your keyboard to activate this mode. - 여기를 클릭하면 피치 조절 모드가 활성화됩니다. 피치 조절 모드에서 음표를 클릭하면 해당 음표의 피치 오토메이션 편집 창을 열 수 있습니다. 이 모드를 이용하여 음표 간 피치 슬라이드를 구현할 수 있습니다. 'Shift+T' 키를 눌러 이 모드를 활성화할 수도 있습니다. - - - Cut selected notes (%1+X) - 선택된 음표 잘라내기 (%1+X) - - - Copy selected notes (%1+C) - 선택된 음표 복사 (%1+C) - - - Paste notes from clipboard (%1+V) - 선택된 음표 붙여넣기 (%1+V) - - - Click here and the selected notes will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. - 여기를 클릭하면 선택한 음표를 클립보드로 잘라낼 수 있습니다. 붙여넣기 버튼을 이용하여 다시 붙여넣을 수 있습니다. - - - Click here and the selected notes will be copied into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. - 여기를 클릭하면 선택한 음표를 클립보드로 복사할 수 있습니다. 붙여넣기 버튼을 이용하여 다시 붙여넣을 수 있습니다. - - - Click here and the notes from the clipboard will be pasted at the first visible measure. - - - - This controls the magnification of an axis. It can be helpful to choose magnification for a specific task. For ordinary editing, the magnification should be fitted to your smallest notes. - - - - The 'Q' stands for quantization, and controls the grid size notes and control points snap to. With smaller quantization values, you can draw shorter notes in Piano Roll, and more exact control points in the Automation Editor. - - - - This lets you select the length of new notes. 'Last Note' means that LMMS will use the note length of the note you last edited - - - - The feature is directly connected to the context-menu on the virtual keyboard, to the left in Piano Roll. After you have chosen the scale you want in this drop-down menu, you can right click on a desired key in the virtual keyboard, and then choose 'Mark current Scale'. LMMS will highlight all notes that belongs to the chosen scale, and in the key you have selected! - - - - Let you select a chord which LMMS then can draw or highlight.You can find the most common chords in this drop-down menu. After you have selected a chord, click anywhere to place the chord, and right click on the virtual keyboard to open context menu and highlight the chord. To return to single note placement, you need to choose 'No chord' in this drop-down menu. - - - - Edit actions - 편집 동작 + Quantize + Copy paste controls @@ -5704,11 +5585,11 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator Timeline controls - + Zoom and note controls - + Piano-Roll - %1 @@ -5719,15 +5600,51 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator 피아노-롤 - 패턴 없음 - Quantize - + Record notes from MIDI-device/channel-piano, one step at the time + + + + Cut (%1+X) + 잘라내기 (%1+X) + + + Copy (%1+C) + 복사 (%1+C) + + + Paste (%1+V) + 붙여넣기 (%1+V) + + + Horizontal zooming + + + + Quantization + + + + Note length + 음표 길이 + + + Scale + + + + Chord + + + + Clear ghost notes + PianoView Base note - + 기준 음 @@ -5737,7 +5654,7 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator 플러그인을 찾을 수 없음 - The plugin "%1" wasn't found or could not be loaded! + The plugin "%1" wasn't found or could not be loaded! Reason: "%2" 플러그인 "%1"을(를) 찾을 수 없거나 읽어올 수 없습니다. 이유: %2 @@ -5753,6 +5670,10 @@ Reason: "%2" PluginBrowser + + Instrument Plugins + 악기 플러그인 + Instrument browser 악기 탐색기 @@ -5761,10 +5682,6 @@ Reason: "%2" Drag an instrument into either the Song-Editor, the Beat+Bassline Editor or into an existing instrument track. 플러그인을 노래 편집기, 비트/베이스 라인 편집기, 이미 존재하는 악기 트랙 중 하나로 드래그하세요. - - Instrument Plugins - 악기 플러그인 - PluginFactory @@ -5781,7 +5698,7 @@ Reason: "%2" ProjectNotes Edit Actions - + 편집 동작 &Undo @@ -5789,7 +5706,7 @@ Reason: "%2" %1+Z - + %1+Z &Redo @@ -5797,7 +5714,7 @@ Reason: "%2" %1+Y - + %1+Y &Copy @@ -5805,7 +5722,7 @@ Reason: "%2" %1+C - + %1+C Cu&t @@ -5813,7 +5730,7 @@ Reason: "%2" %1+X - + %1+X &Paste @@ -5821,11 +5738,11 @@ Reason: "%2" %1+V - + %1+V Format Actions - + 서식 동작 &Bold @@ -5833,15 +5750,15 @@ Reason: "%2" %1+B - + %1+B &Italic - + 기울임꼴(&I) %1+I - + %1+I &Underline @@ -5849,7 +5766,7 @@ Reason: "%2" %1+U - + %1+U &Left @@ -5857,7 +5774,7 @@ Reason: "%2" %1+L - + %1+L C&enter @@ -5865,7 +5782,7 @@ Reason: "%2" %1+E - + %1+E &Right @@ -5873,7 +5790,7 @@ Reason: "%2" %1+R - + %1+R &Justify @@ -5881,7 +5798,7 @@ Reason: "%2" %1+J - + %1+J &Color... @@ -5899,20 +5816,20 @@ Reason: "%2" ProjectRenderer - WAV-File (*.wav) - Wave 파일(*.wav) + WAV (*.wav) + WAV (*.wav) - Compressed OGG-File (*.ogg) - 압축 OGG 파일(*.ogg) + FLAC (*.flac) + FLAC (*.flac) - FLAC-File (*.flac) - FLAC 파일(*.flac) + OGG (*.ogg) + OGG (*.ogg) - Compressed MP3-File (*.mp3) - 압축 MP3 파일(*.mp3) + MP3 (*.mp3) + MP3 (*.mp3) @@ -5931,7 +5848,7 @@ Reason: "%2" Requires Real Time: - + Yes @@ -5951,20 +5868,20 @@ Reason: "%2" Channels In: - 입력 채널: + 입력 채널: Channels Out: - 출력 채널: - - - File: - 파일: + 출력 채널: File: %1 파일: %1 + + File: + 파일: + RenameDialog @@ -5979,60 +5896,72 @@ Reason: "%2" Input 입력 - - Input Gain: - 입력 이득: - Size - + 크기 Size: - + 크기: Color - + 음색 Color: - + 음색: Output 출력 - Output Gain: + Input gain: + 입력 이득: + + + Output gain: 출력 이득: ReverbSCControls - - Input Gain - 입력 이득 - Size - + 크기 Color - + 음색 - Output Gain + Input gain + 입력 이득 + + + Output gain 출력 이득 SampleBuffer + + Fail to open file + 파일을 열 수 없음 + + + Audio files are limited to %1 MB in size and %2 minutes of playing time + 오디오 파일은 %1MB보다 작고 %2분보다 짧아야 합니다 + Open audio file 오디오 파일 열기 + + All Audio-Files (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw) + 모든 오디오 파일 (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw) + Wave-Files (*.wav) Wave 파일(*.wav) @@ -6063,31 +5992,15 @@ Reason: "%2" AU-Files (*.au) - + AU 파일 (*.au) RAW-Files (*.raw) - - - - All Audio-Files (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw) - 모든 오디오 파일 (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw) - - - Fail to open file - 파일을 열 수 없음 - - - Audio files are limited to %1 MB in size and %2 minutes of playing time - 오디오 파일은 %1MB보다 작고 %2분보다 짧아야 합니다 + RAW 파일 (*.raw) SampleTCOView - - double-click to select sample - 더블클릭하여 샘플 선택 - Delete (middle mousebutton) 삭제(마우스 가운데 버튼) @@ -6108,35 +6021,43 @@ Reason: "%2" Mute/unmute (<%1> + middle click) 음소거/해제 (<%1> + 마우스 가운데 버튼) + + Double-click to open sample + 더블클릭하여 샘플 열기 + SampleTrack + + Volume + 음량 + + + Panning + 패닝 + Sample track 샘플 트랙 - Volume - 볼륨 - - - Panning - 패닝 + FX channel + FX 채널 SampleTrackView Track volume - 트랙 볼륨 + 트랙 음량 Channel volume: - 채널 볼륨: + 채널 음량: VOL - 볼륨 + 음량 Panning @@ -6150,6 +6071,56 @@ Reason: "%2" PAN 패닝 + + FX %1: %2 + FX %1: %2 + + + + SampleTrackWindow + + GENERAL SETTINGS + 일반 설정 + + + Sample volume + 샘플 음량 + + + Volume: + 음량: + + + VOL + 음량 + + + Panning + 패닝 + + + Panning: + 패닝: + + + PAN + 패닝 + + + FX channel + FX 채널 + + + FX + FX + + + + SaveOptionsWidget + + Discard MIDI connections + MIDI 연결 제거 + SetupDialog @@ -6165,57 +6136,33 @@ Reason: "%2" BUFFER SIZE 버퍼 크기 - - Reset to default-value - 기본값으로 초기화 - MISC 기타 - Enable tooltips - 툴팁 활성화 + Use built-in NaN handler + - Show restart warning after changing settings - 설정을 변경했을 때 다시 시작 경고 표시 + PLUGIN EMBEDDING + - Compress project files per default - 기본적으로 프로젝트 파일을 압축 + No embedding + - One instrument track window mode - + Embed using Qt API + - HQ-mode for output audio-device - 고품질 오디오 출력 모드 + Embed using native Win32 API + - Compact track buttons - - - - Sync VST plugins to host playback - - - - Enable note labels in piano roll - - - - Enable waveform display by default - 기본적으로 파형 표시를 활성화 - - - Keep effects running even without input - 입력이 없을 때에도 효과 작동 유지 - - - Create backup file when saving a project - 저장할 때 백업 파일 생성 + Embed using XEmbed protocol + LANGUAGE @@ -6226,29 +6173,25 @@ Reason: "%2" 경로 - LMMS working directory - LMMS 작업 경로 - - - VST-plugin directory - VST 플러그인 경로 - - - Background artwork - 배경 아트워크 - - - STK rawwave directory - - - - Default Soundfont File - 기본 사운드폰트 파일 + Directories + 경로 Performance settings 성능 설정 + + Auto save + 자동 저장 + + + Enable auto-save + 자동 저장 활성화 + + + Allow auto-save while playing + 재생 중 자동 저장 허용 + UI effects vs. performance UI 효과 vs. 성능 @@ -6259,7 +6202,7 @@ Reason: "%2" Show playback cursor in AudioFileProcessor - + Audio settings @@ -6291,7 +6234,7 @@ Reason: "%2" Please note that most changes won't take effect until you restart LMMS! - + Frames: %1 @@ -6299,14 +6242,18 @@ Latency: %2 ms 프레임: %1 시간 지연: %2 ms - - Here you can setup the internal buffer-size used by LMMS. Smaller values result in a lower latency but also may cause unusable sound or bad performance, especially on older computers or systems with a non-realtime kernel. - 여기에서 LMMS 내부 버퍼 크기를 설정할 수 있습니다. 작은 값을 설정하면 시간 지연이 감소하지만 음질 저하나 성능 저하가 일어날 수 있습니다. 이러한 현상은 실시간 커널을 가지지 않는 오래된 시스템에서 자주 발생합니다. - Choose LMMS working directory LMMS 작업 경로 선택 + + Choose your GIG directory + GIG 경로 선택 + + + Choose your SF2 directory + SF2 경로 선택 + Choose your VST-plugin directory VST 플러그인 경로 선택 @@ -6321,7 +6268,7 @@ Latency: %2 ms Choose STK rawwave directory - + Choose default SoundFont @@ -6331,50 +6278,6 @@ Latency: %2 ms Choose background artwork 배경 아트워크 선택 - - Here you can select your preferred audio-interface. Depending on the configuration of your system during compilation time you can choose between ALSA, JACK, OSS and more. Below you see a box which offers controls to setup the selected audio-interface. - - - - Here you can select your preferred MIDI-interface. Depending on the configuration of your system during compilation time you can choose between ALSA, OSS and more. Below you see a box which offers controls to setup the selected MIDI-interface. - - - - Reopen last project on start - 시작할 때 마지막에 연 프로젝트 열기 - - - Directories - 경로 - - - Themes directory - 테마 경로 - - - GIG directory - GIG 경로 - - - SF2 directory - SF2 경로 - - - LADSPA plugin directories - LADSPA 플러그인 경로 - - - Auto save - 자동 저장 - - - Choose your GIG directory - GIG 경로 선택 - - - Choose your SF2 directory - SF2 경로 선택 - minutes @@ -6383,18 +6286,6 @@ Latency: %2 ms minute - - Display volume as dBFS - 볼륨을 dBFS 단위로 표시 - - - Enable auto-save - 자동 저장 활성화 - - - Allow auto-save while playing - 재생 중 자동 저장 허용 - Disabled 비활성화됨 @@ -6404,10 +6295,12 @@ Latency: %2 ms 자동 저장 간격: %1 - Set the time between automatic backup to %1. -Remember to also save your project manually. You can choose to disable saving while playing, something some older systems find difficult. - 자동 백업의 시간 간격을 %1(으)로 설정합니다. -여전히 프로젝트를 수동으로 저장하는 것을 추천합니다. 재생 중 자동 저장을 비활성화할 수 있으며 일부 오래된 시스템에서는 잘 작동하지 않을 수 있습니다. + Reset to default value + + + + Keep plugin windows on top when not embedded + @@ -6418,79 +6311,19 @@ Remember to also save your project manually. You can choose to disable saving wh Master volume - 마스터 볼륨 + 마스터 음량 Master pitch 마스터 피치 - - Project saved - 프로젝트 저장됨 - - - The project %1 is now saved. - 프로젝트 %1이 저장되었습니다. - - - Project NOT saved. - 프로젝트가 저장되지 않았습니다. - - - The project %1 was not saved! - 프로젝트 %1이 저장되지 않았습니다! - - - Import file - 파일 가져오기 - - - MIDI sequences - MIDI 시퀀스 - - - Hydrogen projects - Hydrogen 프로젝트 - - - All file types - 모든 파일 - - - Empty project - 빈 프로젝트 - - - This project is empty so exporting makes no sense. Please put some items into Song Editor first! - 빈 프로젝트를 내보내는 것은 무의미합니다. 먼저 노래 편집기에 항목을 추가하시기 바랍니다! - - - Select directory for writing exported tracks... - - - - untitled - 제목 없음 - - - Select file for project-export... - 프로젝트를 내보낼 파일 선택... - - - The following errors occured while loading: - 로딩 중 다음과 같은 오류가 발생하였습니다: - - - MIDI File (*.mid) - MIDI 파일(*.mid) - LMMS Error report LMMS 오류 보고 - Save project - 프로젝트 저장 + The following errors occured while loading: + 로딩 중 다음과 같은 오류가 발생하였습니다: @@ -6499,14 +6332,18 @@ Remember to also save your project manually. You can choose to disable saving wh Could not open file 파일을 열 수 없음 + + Could not open file %1. You probably have no permissions to read this file. + Please make sure to have at least read permissions to the file and try again. + 파일 %1을(를) 열 수 없습니다. 파일을 읽을 수 있는 권한이 없기 때문일 수 있습니다. 파일을 읽을 수 있는 권한이 있는지 확인 후 다시 시도하시기 바랍니다. + Could not write file 파일을 쓸 수 없음 - Could not open file %1. You probably have no permissions to read this file. - Please make sure to have at least read permissions to the file and try again. - 파일 %1을(를) 열 수 없습니다. 파일을 읽을 수 있는 권한이 없기 때문일 수 있습니다. 파일을 읽을 수 있는 권한이 있는지 확인 후 다시 시도하시기 바랍니다. + Could not open %1 for writing. You probably are not permitted to write to this file. Please make sure you have write-access to the file and try again. + 파일 %1을(를) 쓰기 위하여 열 수 없습니다. 파일을 쓸 수 있는 권한이 없기 때문일 수 있습니다. 파일에 쓸 수 있는 권한이 있는지 확인 후 다시 시도하시기 바랍니다. Error in file @@ -6516,42 +6353,38 @@ Remember to also save your project manually. You can choose to disable saving wh The file %1 seems to contain errors and therefore can't be loaded. 파일 %1에 오류가 있어 로딩에 실패하였습니다. + + Version difference + 버전 차이 + + + This %1 was created with LMMS %2. + 이 %1은(는) LMMS %2에서 만들어졌습니다. + + + template + 템플릿 + + + project + 프로젝트 + Tempo 템포 - - TEMPO/BPM - 템포/BPM - - - tempo of song - 템포 - - - The tempo of a song is specified in beats per minute (BPM). If you want to change the tempo of your song, change this value. Every measure has four beats, so the tempo in BPM specifies, how many measures / 4 should be played within a minute (or how many measures should be played within four minutes). - 곡의 템포는 분당 박자 수(BPM) 단위로 설정할 수 있습니다. 이 값을 바꾸면 곡의 템포를 바꿀 수 있습니다. 한 마디가 4박자인 일반적인 경우 BPM 단위의 템포는 분당 재생되는 1 / 4 마디의 수(4분당 재생되는 마디의 수)와 같습니다. - High quality mode 고음질 모드 Master volume - 마스터 볼륨 - - - master volume - 마스터 볼륨 + 마스터 음량 Master pitch 마스터 피치 - - master pitch - 마스터 피치 - Value: %1% 값: %1% @@ -6561,24 +6394,12 @@ Remember to also save your project manually. You can choose to disable saving wh 값: %1반음 - Could not open %1 for writing. You probably are not permitted to write to this file. Please make sure you have write-access to the file and try again. - 파일 %1을(를) 쓰기 위하여 열 수 없습니다. 파일을 쓸 수 있는 권한이 없기 때문일 수 있습니다. 파일에 쓸 수 있는 권한이 있는지 확인 후 다시 시도하시기 바랍니다. + TEMPO + 템포 - template - 템플릿 - - - project - 프로젝트 - - - Version difference - 버전 차이 - - - This %1 was created with LMMS %2. - 이 %1은(는) LMMS %2에서 만들어졌습니다. + Tempo in BPM + BPM 단위의 템포 @@ -6603,6 +6424,10 @@ Remember to also save your project manually. You can choose to disable saving wh Stop song (Space) 노래 정지 (Space) + + Track actions + + Add beat/bassline 비트/베이스 라인 추가 @@ -6615,6 +6440,10 @@ Remember to also save your project manually. You can choose to disable saving wh Add automation-track 오토메이션 트랙 추가 + + Edit actions + 편집 동작 + Draw mode 그리기 모드 @@ -6623,29 +6452,17 @@ Remember to also save your project manually. You can choose to disable saving wh Edit mode (select and move) 편집 모드 (선택 및 이동) - - Click here, if you want to play your whole song. Playing will be started at the song-position-marker (green). You can also move it while playing. - - - - Click here, if you want to stop playing of your song. The song-position-marker will be set to the start of your song. - - - - Track actions - - - - Edit actions - 편집 동작 - Timeline controls - + Zoom controls - + + + + Horizontal zooming + @@ -6674,6 +6491,17 @@ Remember to also save your project manually. You can choose to disable saving wh 채널 모드 + + StepRecorderWidget + + Hint + + + + Move recording curser using <Left/Right> arrows + + + SubWindow @@ -6740,7 +6568,7 @@ Remember to also save your project manually. You can choose to disable saving wh Custom - 사용자 지정 + 사용자 지정 Synced to Eight Beats @@ -6773,10 +6601,6 @@ Remember to also save your project manually. You can choose to disable saving wh TimeDisplayWidget - - click to change time units - 클릭하여 시간 단위 바꾸기 - MIN @@ -6801,17 +6625,13 @@ Remember to also save your project manually. You can choose to disable saving wh TICK + + Time units + 시간 단위 + TimeLineWidget - - Enable/disable auto-scrolling - 자동 스크롤 활성화/비활성화 - - - Enable/disable loop-points - 루프 활성화/비활성화 - After stopping go back to begin 정지한 뒤 시작점으로 이동 @@ -6826,15 +6646,23 @@ Remember to also save your project manually. You can choose to disable saving wh Hint - + Press <%1> to disable magnetic loop points. - + <%1> 키를 눌러 반복 지점을 자유롭게 이동할 수 있습니다. Hold <Shift> to move the begin loop point; Press <%1> to disable magnetic loop points. - + <Shift> 키를 누르면 반복 시작점을 움직일 수 있습니다; <%1> 키를 눌러 반복 지점을 자유롭게 움직일 수 있습니다. + + + Auto scrolling + 자동 스크롤 + + + Loop points + 루프 지점 @@ -6855,16 +6683,17 @@ Remember to also save your project manually. You can choose to disable saving wh 파일을 가져올 수 없음 - Couldn't find a filter for importing file %1. + Couldn't find a filter for importing file %1. You should convert this file into a format supported by LMMS using another software. - + 파일 %1을(를) 가져오기 위한 필터를 찾을 수 없습니다. +이 파일을 가져오려면 다른 프로그램을 사용하여 LMMS가 지원하는 포맷으로 변환하시기 바랍니다. Couldn't open file 파일을 열 수 없음 - Couldn't open file %1 for reading. + Couldn't open file %1 for reading. Please make sure you have read-permission to the file and the directory containing the file and try again! 파일 %1을(를) 읽기 열 수 없습니다. 파일을 읽을 수 있는 권한이 있는지 확인 후 다시 시도하시기 바랍니다! @@ -6881,13 +6710,21 @@ Please make sure you have read-permission to the file and the directory containi 잠시만 기다려 주세요... - Importing MIDI-file... - MIDI 파일을 가져오는중... + Loading cancelled + 로딩 취소됨 + + + Project loading was cancelled. + 프로젝트 로딩이 취소되었습니다. Loading Track %1 (%2/Total %3) 트랙 %1 로딩 중 (%2/총 %3) + + Importing MIDI-file... + MIDI 파일을 가져오는중... + TrackContentObject @@ -6904,7 +6741,7 @@ Please make sure you have read-permission to the file and the directory containi Hint - + Press <%1> and drag to make a copy. @@ -6920,7 +6757,7 @@ Please make sure you have read-permission to the file and the directory containi %1:%2 (%3:%4 to %5:%6) - %1:%2 (%3:%4부터 %5:%6까지) + %1:%2 (%3:%4부터 %5:%6까지) Delete (middle mousebutton) @@ -6945,14 +6782,6 @@ Please make sure you have read-permission to the file and the directory containi TrackOperationsWidget - - Press <%1> while clicking on move-grip to begin a new drag'n'drop-action. - - - - Actions for this track - - Mute 음소거 @@ -6961,10 +6790,6 @@ Please make sure you have read-permission to the file and the directory containi Solo 독주 - - Mute this track - 이 트랙 음소거 - Clone this track 트랙 복제 @@ -6981,160 +6806,140 @@ Please make sure you have read-permission to the file and the directory containi FX %1: %2 FX %1: %2 + + Assign to new FX Channel + 새 FX 채널 할당 + Turn all recording on - + Turn all recording off - + - Assign to new FX Channel - 새 FX 채널 할당 + Press <%1> while clicking on move-grip to begin a new drag'n'drop action. + + + + Actions + TripleOscillatorView - - Use phase modulation for modulating oscillator 1 with oscillator 2 - - - - Use amplitude modulation for modulating oscillator 1 with oscillator 2 - - - - Mix output of oscillator 1 & 2 - - Synchronize oscillator 1 with oscillator 2 - - - - Use frequency modulation for modulating oscillator 1 with oscillator 2 - - - - Use phase modulation for modulating oscillator 2 with oscillator 3 - - - - Use amplitude modulation for modulating oscillator 2 with oscillator 3 - - - - Mix output of oscillator 2 & 3 - + Synchronize oscillator 2 with oscillator 3 - - - - Use frequency modulation for modulating oscillator 2 with oscillator 3 - + Osc %1 volume: - 오실레이터 %1 볼륨: - - - With this knob you can set the volume of oscillator %1. When setting a value of 0 the oscillator is turned off. Otherwise you can hear the oscillator as loud as you set it here. - + 오실레이터 %1 음량: Osc %1 panning: - - - - With this knob you can set the panning of the oscillator %1. A value of -100 means 100% left and a value of 100 moves oscillator-output right. - + 오실레이터 %1 패닝: Osc %1 coarse detuning: - + semitones 반음 - - With this knob you can set the coarse detuning of oscillator %1. You can detune the oscillator 24 semitones (2 octaves) up and down. This is useful for creating sounds with a chord. - 이 노브를 사용하여 오실레이터 %1의 피치를 조절할 수 있습니다. 24반음(두 옥타브) 범위 내에서 조절이 가능합니다. 이 기능은 화음을 가지는 소리를 합성할 때 유용하게 사용될 수 있습니다. - Osc %1 fine detuning left: - + cents 센트 - - With this knob you can set the fine detuning of oscillator %1 for the left channel. The fine-detuning is ranged between -100 cents and +100 cents. This is useful for creating "fat" sounds. - 이 노브를 사용하여 오실레이터 %1의 왼쪽 채널 음정을 미세 조절할 수 있습니다. -100센트부터 +100센트까지의 범위 내에서 조절이 가능합니다. 이 기능은 풍성한 소리를 합성할 때 유용하게 사용될 수 있습니다. - Osc %1 fine detuning right: - - - - With this knob you can set the fine detuning of oscillator %1 for the right channel. The fine-detuning is ranged between -100 cents and +100 cents. This is useful for creating "fat" sounds. - 이 노브를 사용하여 오실레이터 %1의 오른쪽 채널 음정을 미세 조절할 수 있습니다. -100센트부터 +100센트까지의 범위 내에서 조절이 가능합니다. 이 기능은 풍성한 소리를 합성할 때 유용하게 사용될 수 있습니다. + Osc %1 phase-offset: - + degrees - - With this knob you can set the phase-offset of oscillator %1. That means you can move the point within an oscillation where the oscillator begins to oscillate. For example if you have a sine-wave and have a phase-offset of 180 degrees the wave will first go down. It's the same with a square-wave. - - Osc %1 stereo phase-detuning: - + - With this knob you can set the stereo phase-detuning of oscillator %1. The stereo phase-detuning specifies the size of the difference between the phase-offset of left and right channel. This is very good for creating wide stereo sounds. - + Modulate phase of oscillator 1 by oscillator 2 + - Use a sine-wave for current oscillator. - 이 오실레이터에 사인파 사용 + Modulate amplitude of oscillator 1 by oscillator 2 + - Use a triangle-wave for current oscillator. - 이 오실레이터에 삼각파 사용 + Mix output of oscillators 1 & 2 + - Use a saw-wave for current oscillator. - 이 오실레이터에 톱니파 사용 + Modulate frequency of oscillator 1 by oscillator 2 + - Use a square-wave for current oscillator. - 이 오실레이터에 사각파 사용 + Modulate phase of oscillator 2 by oscillator 3 + - Use a moog-like saw-wave for current oscillator. - + Modulate amplitude of oscillator 2 by oscillator 3 + - Use an exponential wave for current oscillator. - + Mix output of oscillators 2 & 3 + - Use white-noise for current oscillator. - + Modulate frequency of oscillator 2 by oscillator 3 + - Use a user-defined waveform for current oscillator. - 이 오실레이터에 사용자 지정 파형 사용 + Sine wave + 사인파 + + + Triangle wave + 삼각파 + + + Saw wave + 톱니파 + + + Square wave + 사각파 + + + Moog-like saw wave + Moog 톱니파 + + + Exponential wave + 지수형 파형 + + + White noise + 화이트 노이즈 + + + User-defined wave + 사용자 지정 파형 @@ -7149,35 +6954,35 @@ Please make sure you have read-permission to the file and the directory containi already exists. Do you want to replace it? - 파일이 이미 존재합니다. 덮어쓰시겠습니까? + 이(가) 이미 존재합니다. 덮어쓰시겠습니까? + + + Save Options + 저장 옵션 VestigeInstrumentView - Open other VST-plugin - 다른 VST 플러그인 열기 + Previous (-) + 이전 (-) - Click here, if you want to open another VST-plugin. After clicking on this button, a file-open-dialog appears and you can select your file. - + Save preset + 프리셋 저장 + + + Next (+) + 다음 (+) Show/hide GUI GUI 보이기/숨기기 - - Click here to show or hide the graphical user interface (GUI) of your VST-plugin. - - Turn off all notes 모든 음 끄기 - - Open VST-plugin - VST 플러그인 열기 - DLL-files (*.dll) DLL 파일 (*.dll) @@ -7186,73 +6991,45 @@ Please make sure you have read-permission to the file and the directory containi EXE-files (*.exe) EXE 파일 (*.exe) - - No VST-plugin loaded - VST 플러그인이 로딩되지 않음 - - - Control VST-plugin from LMMS host - LMMS에서 VST 플러그인 제어 - - - Click here, if you want to control VST-plugin from host. - LMMS에서 VST 플러그인을 제어하려면 여기를 클릭하세요. - - - Open VST-plugin preset - VST-플러그인 프리셋 열기 - - - Click here, if you want to open another *.fxp, *.fxb VST-plugin preset. - - - - Previous (-) - 이전 (-) - - - Click here, if you want to switch to another VST-plugin preset program. - - - - Save preset - 프리셋 저장 - - - Click here, if you want to save current VST-plugin preset program. - - - - Next (+) - 다음 (+) - - - Click here to select presets that are currently loaded in VST. - - Preset 프리셋 by - + - VST plugin control - + + + + Open VST plugin + + + + Control VST plugin from LMMS host + + + + Open VST plugin preset + + + + No VST plugin loaded + VisualizationWidget - - click to enable/disable visualization of master-output - 클릭하여 출력 파형 표시 활성화/비활성화 - Click to enable 클릭하여 활성화 + + Oscilloscope + 오실로스코프 + VstEffectControlDialog @@ -7260,60 +7037,40 @@ Please make sure you have read-permission to the file and the directory containi Show/hide 보이기/숨기기 - - Control VST-plugin from LMMS host - LMMS에서 VST 플러그인 제어 - - - Click here, if you want to control VST-plugin from host. - LMMS에서 VST 플러그인을 제어하려면 여기를 클릭하세요. - - - Open VST-plugin preset - VST-플러그인 프리셋 열기 - - - Click here, if you want to open another *.fxp, *.fxb VST-plugin preset. - - Previous (-) 이전 (-) - - Click here, if you want to switch to another VST-plugin preset program. - - Next (+) 다음 (+) - - Click here to select presets that are currently loaded in VST. - - Save preset 프리셋 저장 - - Click here, if you want to save current VST-plugin preset program. - - Effect by: - + &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /> + + Control VST plugin from LMMS host + + + + Open VST plugin preset + + VstPlugin - Loading plugin - 플러그인 읽는 중 + The VST plugin %1 could not be loaded. + VST 플러그인 %1을 불러올 수 없습니다. Open Preset @@ -7325,15 +7082,15 @@ Please make sure you have read-permission to the file and the directory containi : default - + " - + ' - + Save Preset @@ -7356,31 +7113,31 @@ Please make sure you have read-permission to the file and the directory containi .fxb - Please wait while loading VST plugin... - VST 플러그인을 읽을 동안 잠시 기다려 주세요... + Loading plugin + 플러그인 읽는 중 - The VST plugin %1 could not be loaded. - VST 플러그인 %1을 불러올 수 없습니다. + Please wait while loading VST plugin... + VST 플러그인을 읽을 동안 잠시 기다려 주세요... WatsynInstrument Volume A1 - A1 볼륨 + A1 음량 Volume A2 - A2 볼륨 + A2 음량 Volume B1 - B1 볼륨 + B1 음량 Volume B2 - B2 볼륨 + B2 음량 Panning A1 @@ -7400,138 +7157,162 @@ Please make sure you have read-permission to the file and the directory containi Freq. multiplier A1 - + Freq. multiplier A2 - + Freq. multiplier B1 - + Freq. multiplier B2 - + Left detune A1 - + Left detune A2 - + Left detune B1 - + Left detune B2 - + Right detune A1 - + Right detune A2 - + Right detune B1 - + Right detune B2 - + A-B Mix - + A-B Mix envelope amount - + A-B Mix envelope attack - + A-B Mix envelope hold - + A-B Mix envelope decay - + A1-B2 Crosstalk - + A2-A1 modulation - + B2-B1 modulation - + Selected graph - + 선택된 그래프 WatsynView + + Volume + 음량 + + + Panning + 패닝 + + + Freq. multiplier + + + + Left detune + + + + cents + 센트 + + + Right detune + + + + A-B Mix + + + + Mix envelope amount + + + + Mix envelope attack + + + + Mix envelope hold + + + + Mix envelope decay + + + + Crosstalk + + Select oscillator A1 - + Select oscillator A2 - + Select oscillator B1 - + Select oscillator B2 - + Mix output of A2 to A1 - - - - Modulate amplitude of A1 with output of A2 - - - - Ring-modulate A1 and A2 - - - - Modulate phase of A1 with output of A2 - + Mix output of B2 to B1 - - - - Modulate amplitude of B1 with output of B2 - - - - Ring-modulate B1 and B2 - - - - Modulate phase of B1 with output of B2 - + Draw your own waveform here by dragging your mouse on this graph. @@ -7541,125 +7322,219 @@ Please make sure you have read-permission to the file and the directory containi Load waveform 파형 불러오기 - - Click to load a waveform from a sample file - 샘플 파일에서 파형 가져오기 - Phase left 왼쪽 위상 - - Click to shift phase by -15 degrees - 위상을 -15도만큼 바꾸기 - Phase right 오른쪽 위상 - - Click to shift phase by +15 degrees - 위상을 +15도만큼 바꾸기 - Normalize 일반화 - - Click to normalize - 클릭하여 규격화 - Invert 파형 반전 - - Click to invert - 클릭하여 파형 반전 - Smooth 부드럽게 - - Click to smooth - 클릭하여 파형을 부드럽게 - Sine wave 사인파 - - Click for sine wave - 클릭하여 사인파 선택 - Triangle wave 삼각파 - - Click for triangle wave - 클릭하여 삼각파 선택 - - - Click for saw wave - 클릭하여 톱니파 선택 - Square wave 사각파 - Click for square wave - 클릭하여 사각파 선택 + Modulate amplitude of A1 by output of A2 + - Volume - 볼륨 + Ring modulate A1 and A2 + - Panning - 패닝 + Modulate phase of A1 by output of A2 + - Freq. multiplier - + Modulate amplitude of B1 by output of B2 + - Left detune - + Ring modulate B1 and B2 + - cents - 센트 + Modulate phase of B1 by output of B2 + - Right detune - + Load a waveform from a sample file + - A-B Mix - + Shift phase by -15 degrees + - Mix envelope amount - + Shift phase by +15 degrees + - Mix envelope attack - + Saw wave + 톱니파 + + + + Xpressive + + Selected graph + 선택된 그래프 - Mix envelope hold - + A1 + - Mix envelope decay - + A2 + - Crosstalk - + A3 + + + + W1 smoothing + + + + W2 smoothing + + + + W3 smoothing + + + + Panning 1 + + + + Panning 2 + + + + Rel trans + + + + + XpressiveView + + Draw your own waveform here by dragging your mouse on this graph. + 드래그하여 원하는 파형을 그리세요. + + + Select oscillator W1 + + + + Select oscillator W2 + + + + Select oscillator W3 + + + + Select output O1 + + + + Select output O2 + + + + Open help window + + + + Sine wave + 사인파 + + + Moog-saw wave + + + + Exponential wave + 지수형 파형 + + + Saw wave + 톱니파 + + + User-defined wave + + + + Triangle wave + 삼각파 + + + Square wave + 사각파 + + + White noise + 화이트 노이즈 + + + WaveInterpolate + + + + ExpressionValid + + + + General purpose 1: + + + + General purpose 2: + + + + General purpose 3: + + + + O1 panning: + + + + O2 panning: + + + + Release transition: + + + + Smoothness + @@ -7668,45 +7543,37 @@ Please make sure you have read-permission to the file and the directory containi Portamento 포르타멘토 - - Filter Frequency - 필터 주파수 - - - Filter Resonance - 필터 공명 - Bandwidth 대역폭 - FM Gain - + Filter frequency + - Resonance Center Frequency - + Filter resonance + - Resonance Bandwidth - + FM gain + - Forward MIDI Control Change Events - + Resonance center frequency + + + + Resonance bandwidth + + + + Forward MIDI control change events + ZynAddSubFxView - - Show GUI - GUI 표시 - - - Click here to show or hide the graphical user interface (GUI) of ZynAddSubFX. - 클릭하여 ZynAddSubFX의 GUI를 표시하거나 숨깁니다. - Portamento: 포르타멘토: @@ -7715,18 +7582,10 @@ Please make sure you have read-permission to the file and the directory containi PORT 포르타멘토 - - Filter Frequency: - 필터 주파수: - FREQ 주파수 - - Filter Resonance: - 필터 공명: - RES 공명 @@ -7739,33 +7598,45 @@ Please make sure you have read-permission to the file and the directory containi BW 대역폭 - - FM Gain: - FM 이득: - FM GAIN FM 이득 Resonance center frequency: - + 공명 중심 주파수: RES CF - + Resonance bandwidth: - + 공명 대역폭: RES BW - + - Forward MIDI Control Changes - MIDI 컨트롤 변화(CC) 전달 + Show GUI + GUI 표시 + + + Filter frequency: + + + + Filter resonance: + + + + FM gain: + + + + Forward MIDI control changes + @@ -7782,22 +7653,22 @@ Please make sure you have read-permission to the file and the directory containi End of sample 샘플 끝 + + Loopback point + 루프 시작점 + Reverse sample 샘플 역으로 - - Stutter - - - - Loopback point - - Loop mode 루프 모드 + + Stutter + + Interpolation mode 보간법 @@ -7812,7 +7683,7 @@ Please make sure you have read-permission to the file and the directory containi Sinc - + Sinc Sample not found: %1 @@ -7822,15 +7693,15 @@ Please make sure you have read-permission to the file and the directory containi bitInvader - Samplelength + Sample length 샘플 길이 bitInvaderView - Sample Length - 샘플 길이 + Draw your own waveform here by dragging your mouse on this graph. + 드래그하여 원하는 파형을 그리세요. Sine wave @@ -7848,22 +7719,6 @@ Please make sure you have read-permission to the file and the directory containi Square wave 사각파 - - White noise wave - 화이트 노이즈 - - - User defined wave - 사용자 정의파 - - - Smooth - 부드럽게 - - - Click here to smooth waveform. - 클릭하여 파형을 부드럽게 합니다. - Interpolation 보간 @@ -7873,32 +7728,20 @@ Please make sure you have read-permission to the file and the directory containi 규격화 - Draw your own waveform here by dragging your mouse on this graph. - 드래그하여 원하는 파형을 그리세요. + Sample length + 샘플 길이 - Click for a sine-wave. - 클릭하여 사인파를 선택합니다. + White noise + 화이트 노이즈 - Click here for a triangle-wave. - 클릭하여 삼각파를 선택합니다. + User-defined wave + 사용자 지정 파형 - Click here for a saw-wave. - 클릭하여 톱니파를 선택합니다. - - - Click here for a square-wave. - 클릭하여 사각파를 선택합니다. - - - Click here for white-noise. - 클릭하여 화이트 노이즈를 선택합니다. - - - Click here for a user-defined shape. - 클릭하여 사용자 지정 파형을 선택합니다. + Smooth waveform + 파형을 부드럽게 @@ -7921,75 +7764,59 @@ Please make sure you have read-permission to the file and the directory containi ATTACK - + Peak attack time: - + RELEASE - + Peak release time: - - - - Reset waveform - 파형 초기화 - - - Click here to reset the wavegraph back to default - 클릭하여 기본 그래프로 초기화 - - - Smooth waveform - 파형을 부드럽게 - - - Click here to apply smoothing to wavegraph - - - - Increase wavegraph amplitude by 1dB - - - - Click here to increase wavegraph amplitude by 1dB - - - - Decrease wavegraph amplitude by 1dB - - - - Click here to decrease wavegraph amplitude by 1dB - - - - Stereomode Maximum - + Process based on the maximum of both stereo channels - - - - Stereomode Average - + 두 채널의 최댓값을 기준으로 효과 적용 Process based on the average of both stereo channels - - - - Stereomode Unlinked - + 두 채널의 평균을 기준으로 효과 적용 Process each stereo channel independently - + 각각의 채널에 독립적으로 효과 적용 + + + Reset wavegraph + + + + Smooth wavegraph + + + + Increase wavegraph amplitude by 1 dB + + + + Decrease wavegraph amplitude by 1 dB + + + + Stereo mode: maximum + + + + Stereo mode: average + + + + Stereo mode: unlinked + @@ -8004,155 +7831,17 @@ Please make sure you have read-permission to the file and the directory containi Attack time - + Release time - + Stereo mode 스테레오 모드 - - expressiveView - - Select oscillator W1 - - - - Select oscillator W2 - - - - Select oscillator W3 - - - - Select OUTPUT 1 - - - - Select OUTPUT 2 - - - - Open help window - - - - Sine wave - 사인파 - - - Click for a sine-wave. - 클릭하여 사인파를 선택합니다. - - - Moog-Saw wave - - - - Click for a Moog-Saw-wave. - - - - Exponential wave - - - - Click for an exponential wave. - - - - Saw wave - 톱니파 - - - Click here for a saw-wave. - 클릭하여 톱니파를 선택합니다. - - - User defined wave - 사용자 정의 파형 - - - Click here for a user-defined shape. - 클릭하여 사용자 지정 파형을 선택합니다. - - - Triangle wave - 삼각파 - - - Click here for a triangle-wave. - 클릭하여 삼각파를 선택합니다. - - - Square wave - 사각파 - - - Click here for a square-wave. - 클릭하여 사각파를 선택합니다. - - - White noise wave - 화이트 노이즈 - - - Click here for white-noise. - 클릭하여 화이트 노이즈를 선택합니다. - - - WaveInterpolate - - - - ExpressionValid - - - - General purpose 1: - - - - General purpose 2: - - - - General purpose 3: - - - - O1 panning: - - - - O2 panning: - - - - Release transition: - - - - Smoothness - - - - - fxLineLcdSpinBox - - Assign to: - - - - New FX Channel - 새 FX 채널 - - graphModel @@ -8170,25 +7859,13 @@ Please make sure you have read-permission to the file and the directory containi End frequency 끝 주파수 - - Gain - 이득 - Length 길이 - Distortion Start - 디스토션 시작 값 - - - Distortion End - 디스토션 끝 값 - - - Envelope Slope - + Gain + 이득 Noise @@ -8196,19 +7873,31 @@ Please make sure you have read-permission to the file and the directory containi Click - - - - Frequency Slope - + Start from note - + 음표 주파수에서 시작 End to note - + 음표 주파수에서 마침 + + + Start distortion + + + + End distortion + + + + Envelope slope + + + + Frequency slope + @@ -8225,32 +7914,32 @@ Please make sure you have read-permission to the file and the directory containi Gain: 이득: - - Frequency Slope: - - - - Envelope Length: - 엔벨로프 길이: - - - Envelope Slope: - - Click: - + Noise: - + 잡음: - Distortion Start: + Frequency slope: + + + + Envelope length: + 엔벨로프 길이: + + + Envelope slope: + + + + Start distortion: 디스토션 시작 값: - Distortion End: + End distortion: 디스토션 끝 값: @@ -8276,22 +7965,6 @@ Please make sure you have read-permission to the file and the directory containi Don't know 알 수 없음 - - This dialog displays information on all of the LADSPA plugins LMMS was able to locate. The plugins are divided into five categories based upon an interpretation of the port types and names. - -Available Effects are those that can be used by LMMS. In order for LMMS to be able to use an effect, it must, first and foremost, be an effect, which is to say, it has to have both input channels and output channels. LMMS identifies an input channel as an audio rate port containing 'in' in the name. Output channels are identified by the letters 'out'. Furthermore, the effect must have the same number of inputs and outputs and be real time capable. - -Unavailable Effects are those that were identified as effects, but either didn't have the same number of input and output channels or weren't real time capable. - -Instruments are plugins for which only output channels were identified. - -Analysis Tools are plugins for which only input channels were identified. - -Don't Knows are plugins for which no input or output channels were identified. - -Double clicking any of the plugins will bring up information on the ports. - - Type: 형태: @@ -8391,7 +8064,7 @@ Double clicking any of the plugins will bring up information on the ports. VCF Envelope Decay - VCF 엔벨로프 감쇄 + VCF 엔벨로프 감쇠 Distortion @@ -8411,11 +8084,11 @@ Double clicking any of the plugins will bring up information on the ports. Accent - + Dead - + 24dB/oct Filter @@ -8438,15 +8111,15 @@ Double clicking any of the plugins will bring up information on the ports. Decay: - 감쇄: + 감쇠: 303-es-que, 24dB/octave, 3 pole filter - + Slide Decay: - 슬라이드 감쇄: + 슬라이드 감쇠: DIST: @@ -8486,11 +8159,11 @@ Double clicking any of the plugins will bring up information on the ports. Moog wave - 무그 파형 + Moog 톱니파 Click here for a moog-like wave. - 클릭하여 무그 파형을 선택합니다. + 클릭하여 Moog 톱니파를 선택합니다. Sine wave @@ -8514,75 +8187,55 @@ Double clicking any of the plugins will bring up information on the ports. Bandlimited saw wave - + 대역 제한 톱니파 Click here for bandlimited saw wave. - + 클릭하여 대역 제한 톱니파를 선택합니다. Bandlimited square wave - + 대역 제한 사각파 Click here for bandlimited square wave. - + 클릭하여 대역 제한 사각파를 선택합니다. Bandlimited triangle wave - + 대역 제한 삼각파 Click here for bandlimited triangle wave. - + 클릭하여 대역 제한 삼각파를 선택합니다. Bandlimited moog saw wave - + 대역 제한 Moog 톱니파 Click here for bandlimited moog saw wave. - + 클릭하여 대역 제한 Moog 톱니파를 선택합니다. malletsInstrument Hardness - + Position 위치 - - Vibrato Gain - 떨림 이득 - - - Vibrato Freq - 비브라토 주파수 - - - Stick Mix - 스틱 믹스 - Modulator - 모듈레이트 + 모듈레이터 Crossfade 크로스페이드 - - LFO Speed - LFO 속도 - - - LFO Depth - LFO 깊이 - ADSR ADSR @@ -8601,11 +8254,11 @@ Double clicking any of the plugins will bring up information on the ports. Bowed - + Spread - + Marimba @@ -8619,49 +8272,69 @@ Double clicking any of the plugins will bring up information on the ports.Agogo 아고고 - - Wood1 - - Reso - - - - Wood2 - + Beats - - - - Two Fixed - + Clump - - - - Tubular Bells - - - - Uniform Bar - - - - Tuned Bar - + Glass - + 유리 - Tibetan Bowl - + Vibrato gain + + + + Vibrato frequency + + + + Stick mix + + + + LFO speed + LFO 속도 + + + LFO depth + + + + Wood 1 + + + + Wood 2 + + + + Two fixed + + + + Tubular bells + + + + Uniform bar + + + + Tuned bar + + + + Tibetan bowl + @@ -8672,19 +8345,27 @@ Double clicking any of the plugins will bring up information on the ports. Spread - + Spread: - + + + + Missing files + 없는 파일 + + + Your Stk-installation seems to be incomplete. Please make sure the full Stk-package is installed! + Stk 설치가 불완전한 것 같습니다. 완전한 Stk 패키지가 설치되었는지 확인하시기 바랍니다! Hardness - + Hardness: - + Position @@ -8694,37 +8375,13 @@ Double clicking any of the plugins will bring up information on the ports.Position: 위치: - - Vib Gain - - - - Vib Gain: - - - - Vib Freq - - - - Vib Freq: - - - - Stick Mix - - - - Stick Mix: - - Modulator 모듈레이터 Modulator: - + 모듈레이터: Crossfade @@ -8732,23 +8389,7 @@ Double clicking any of the plugins will bring up information on the ports. Crossfade: - - - - LFO Speed - LFO 속도 - - - LFO Speed: - - - - LFO Depth - LFO 깊이 - - - LFO Depth: - + 크로스페이드: ADSR @@ -8756,7 +8397,7 @@ Double clicking any of the plugins will bring up information on the ports. ADSR: - + ADSR: Pressure @@ -8764,7 +8405,7 @@ Double clicking any of the plugins will bring up information on the ports. Pressure: - + 압력: Speed @@ -8772,215 +8413,85 @@ Double clicking any of the plugins will bring up information on the ports. Speed: - + 속도: - Missing files - 없는 파일 + Vibrato gain + - Your Stk-installation seems to be incomplete. Please make sure the full Stk-package is installed! - Stk 설치가 불완전한 것 같습니다. 완전한 Stk 패키지가 설치되었는지 확인하시기 바랍니다! + Vibrato gain: + + + + Vibrato frequency + + + + Vibrato frequency: + + + + Stick mix + + + + Stick mix: + + + + LFO speed + LFO 속도 + + + LFO speed: + LFO 속도: + + + LFO depth + + + + LFO depth: + manageVSTEffectView - VST parameter control - - - - VST Sync - - - - Click here if you want to synchronize all parameters with VST plugin. - + Automated - - - - Click here if you want to display automated parameters only. - + Close - 닫기 + 닫기 - Close VST effect knob-controller window. - + VST sync + VST와 동기화 manageVestigeInstrumentView - VST plugin control - + VST Sync - - - - Click here if you want to synchronize all parameters with VST plugin. - + VST와 동기화 Automated - - - - Click here if you want to display automated parameters only. - + Close - 닫기 - - - Close VST plugin knob-controller window. - - - - - opl2instrument - - Patch - 패치 - - - Op 1 Attack - - - - Op 1 Decay - - - - Op 1 Sustain - - - - Op 1 Release - - - - Op 1 Level - - - - Op 1 Level Scaling - - - - Op 1 Frequency Multiple - - - - Op 1 Feedback - - - - Op 1 Key Scaling Rate - - - - Op 1 Percussive Envelope - - - - Op 1 Tremolo - - - - Op 1 Vibrato - - - - Op 1 Waveform - - - - Op 2 Attack - - - - Op 2 Decay - - - - Op 2 Sustain - - - - Op 2 Release - - - - Op 2 Level - - - - Op 2 Level Scaling - - - - Op 2 Frequency Multiple - - - - Op 2 Key Scaling Rate - - - - Op 2 Percussive Envelope - - - - Op 2 Tremolo - - - - Op 2 Vibrato - - - - Op 2 Waveform - - - - FM - - - - Vibrato Depth - - - - Tremolo Depth - - - - - opl2instrumentView - - Attack - - - - Decay - - - - Release - - - - Frequency multiplier - + 닫기 @@ -8991,7 +8502,7 @@ Double clicking any of the plugins will bring up information on the ports. Volume - 볼륨 + 음량 @@ -9002,11 +8513,11 @@ Double clicking any of the plugins will bring up information on the ports. Volume: - 볼륨: + 음량: Randomise - + 무작위 생성 Osc %1 waveform: @@ -9014,312 +8525,34 @@ Double clicking any of the plugins will bring up information on the ports. Osc %1 volume: - 오실레이터 %1 볼륨: + 오실레이터 %1 음량: Osc %1 panning: - + 오실레이터 %1 패닝: + + + Osc %1 stereo detuning + cents 센트 - - The distortion knob adds distortion to the output of the instrument. - - - - The volume knob controls the volume of the output of the instrument. It is cumulative with the instrument window's volume control. - - - - The randomize button randomizes all knobs except the harmonics,main volume and distortion knobs. - - - - Osc %1 stereo detuning - - Osc %1 harmonic: - - - - - FreeBoyInstrument - - Sweep time - - - - Sweep direction - - - - Sweep RtShift amount - - - - Wave Pattern Duty - - - - Channel 1 volume - - - - Volume sweep direction - - - - Length of each step in sweep - - - - Channel 2 volume - - - - Channel 3 volume - - - - Channel 4 volume - - - - Right Output level - - - - Left Output level - - - - Channel 1 to SO2 (Left) - - - - Channel 2 to SO2 (Left) - - - - Channel 3 to SO2 (Left) - - - - Channel 4 to SO2 (Left) - - - - Channel 1 to SO1 (Right) - - - - Channel 2 to SO1 (Right) - - - - Channel 3 to SO1 (Right) - - - - Channel 4 to SO1 (Right) - - - - Treble - - - - Bass - - - - Shift Register width - - - - - FreeBoyInstrumentView - - Sweep Time: - - - - Sweep Time - - - - Sweep RtShift amount: - - - - Sweep RtShift amount - - - - Wave pattern duty: - - - - Wave Pattern Duty - - - - Square Channel 1 Volume: - - - - Length of each step in sweep: - - - - Length of each step in sweep - - - - Wave pattern duty - - - - Square Channel 2 Volume: - - - - Square Channel 2 Volume - - - - Wave Channel Volume: - - - - Wave Channel Volume - - - - Noise Channel Volume: - - - - Noise Channel Volume - - - - SO1 Volume (Right): - - - - SO1 Volume (Right) - - - - SO2 Volume (Left): - - - - SO2 Volume (Left) - - - - Treble: - - - - Treble - - - - Bass: - - - - Bass - - - - Sweep Direction - - - - Volume Sweep Direction - - - - Shift Register Width - - - - Channel1 to SO1 (Right) - - - - Channel2 to SO1 (Right) - - - - Channel3 to SO1 (Right) - - - - Channel4 to SO1 (Right) - - - - Channel1 to SO2 (Left) - - - - Channel2 to SO2 (Left) - - - - Channel3 to SO2 (Left) - - - - Channel4 to SO2 (Left) - - - - Wave Pattern - - - - The amount of increase or decrease in frequency - - - - The rate at which increase or decrease in frequency occurs - - - - The duty cycle is the ratio of the duration (time) that a signal is ON versus the total period of the signal. - - - - Square Channel 1 Volume - - - - The delay between step change - - - - Draw the wave here - + 오실레이터 %1 배음: patchesDialog Qsynth: Channel Preset - + Bank selector - + Bank @@ -9327,7 +8560,7 @@ Double clicking any of the plugins will bring up information on the ports. Program selector - + Patch @@ -9350,39 +8583,160 @@ Double clicking any of the plugins will bring up information on the ports.pluginBrowser no description - 요약 없음 + 설명 없음 - Incomplete monophonic imitation tb303 - + A native amplifier plugin + 내장 증폭기 플러그인 - Plugin for freely manipulating stereo output - + Simple sampler with various settings for using samples (e.g. drums) in an instrument-track + - Plugin for controlling knobs with sound peaks - + Boost your bass the fast and simple way + - Plugin for enhancing stereo separation of a stereo input file - + Customizable wavetable synthesizer + + + + An oversampling bitcrusher + + + + Carla Patchbay Instrument + + + + Carla Rack Instrument + + + + A 4-band Crossover Equalizer + + + + A native delay plugin + 내장 딜레이 플러그인 + + + A Dual filter plugin + + + + plugin for processing dynamics in a flexible way + + + + A native eq plugin + 내장 EQ 플러그인 + + + A native flanger plugin + 내장 플랜저 플러그인 + + + Player for GIG files + GIG 파일 플레이어 + + + Filter for importing Hydrogen files into LMMS + Hydrogen 파일을 LMMS로 읽어오기 위한 필터 + + + Versatile drum synthesizer + List installed LADSPA plugins 설치된 LADSPA 플러그인 목록 - GUS-compatible patch instrument - + plugin for using arbitrary LADSPA-effects inside LMMS. + LMMS에서 LADSPA 이펙트를 이용하기 위한 플러그인. + + + Incomplete monophonic imitation tb303 + + + + Filter for exporting MIDI-files from LMMS + MIDI 파일을 LMMS에서 내보내기 위한 필터 + + + Filter for importing MIDI-files into LMMS + MIDI 파일을 LMMS로 읽어오기 위한 필터 + + + Monstrous 3-oscillator synth with modulation matrix + + + + A multitap echo delay plugin + + + + A NES-like synthesizer + + + + 2-operator FM Synth + Additive Synthesizer for organ-like sounds - + + + + Emulation of GameBoy (TM) APU + GameBoy (TM) APU 에뮬레이션 + + + GUS-compatible patch instrument + + + + Plugin for controlling knobs with sound peaks + + + + Reverb algorithm by Sean Costello + Sean Costello의 리버브 알고리즘 + + + Player for SoundFont files + 사운드폰트 파일 플레이어 + + + LMMS port of sfxr + + + + Emulation of the MOS6581 and MOS8580 SID. +This chip was used in the Commodore 64 computer. + + + + Graphical spectrum analyzer plugin + 그래픽 스펙트럼 분석 플러그인 + + + Plugin for enhancing stereo separation of a stereo input file + + + + Plugin for freely manipulating stereo output + Tuneful things to bang on - + + + + Three powerful oscillators you can modulate in several ways + VST-host for using VST(i)-plugins within LMMS @@ -9390,148 +8744,27 @@ Double clicking any of the plugins will bring up information on the ports. Vibrating string modeler - - - - plugin for using arbitrary LADSPA-effects inside LMMS. - LMMS에서 LADSPA 이펙트를 이용하기 위한 플러그인. - - - Filter for importing MIDI-files into LMMS - 미디 파일을 LMMS로 읽어오기 위한 필터 - - - Emulation of the MOS6581 and MOS8580 SID. -This chip was used in the Commodore 64 computer. - - - - Player for SoundFont files - 사운드폰트 파일 플레이어 - - - Emulation of GameBoy (TM) APU - - - - Customizable wavetable synthesizer - - - - Embedded ZynAddSubFX - - - - 2-operator FM Synth - - - - Filter for importing Hydrogen files into LMMS - - - - LMMS port of sfxr - - - - Monstrous 3-oscillator synth with modulation matrix - - - - Three powerful oscillators you can modulate in several ways - - - - A native amplifier plugin - - - - Carla Rack Instrument - - - - 4-oscillator modulatable wavetable synth - - - - plugin for waveshaping - - - - Boost your bass the fast and simple way - - - - Versatile drum synthesizer - - - - Simple sampler with various settings for using samples (e.g. drums) in an instrument-track - - - - plugin for processing dynamics in a flexible way - - - - Carla Patchbay Instrument - + plugin for using arbitrary VST effects inside LMMS. - + LMMS에서 VST 이펙트를 이용하기 위한 플러그인. - Graphical spectrum analyzer plugin - + 4-oscillator modulatable wavetable synth + - A NES-like synthesizer - + plugin for waveshaping + - A native delay plugin - - - - Player for GIG files - - - - A multitap echo delay plugin - - - - A native flanger plugin - - - - An oversampling bitcrusher - - - - A native eq plugin - 내장 EQ 플러그인 - - - A 4-band Crossover Equalizer - - - - A Dual filter plugin - - - - Filter for exporting MIDI-files from LMMS - - - - Reverb algorithm by Sean Costello - + Embedded ZynAddSubFX + 내장 ZynAddSubFX 플러그인 Mathematical expression parser - + @@ -9552,135 +8785,111 @@ This chip was used in the Commodore 64 computer. Reverb 리버브 - - Reverb Roomsize - 리버브 룸크기 - - - Reverb Damping - 리버브 댐핑 - - - Reverb Width - 리버브 너비 - - - Reverb Level - 리버브 레벨 - Chorus 코러스 - - Chorus Lines - 코러스 라인 - - - Chorus Level - 코러스 레벨 - - - Chorus Speed - 코러스 속도 - - - Chorus Depth - 코러스 깊이 - A soundfont %1 could not be loaded. 사운드폰트 %1을 불러올 수 없습니다. + + Reverb room size + 리버브 공간 크기 + + + Reverb damping + 리버브 감쇠 + + + Reverb width + 리버브 너비 + + + Reverb level + + + + Chorus voices + + + + Chorus level + + + + Chorus speed + + + + Chorus depth + 코러스 깊이 + sf2InstrumentView - - Open other SoundFont file - 다른 사운드폰트 파일 열기 - - - Click here to open another SF2 file - 클릭하여 다른 SF2 파일 열기 - - - Choose the patch - 패치 선택 - - - Gain - 이득 - Apply reverb (if supported) 리버브 적용(지원시) - - This button enables the reverb effect. This is useful for cool effects, but only works on files that support it. - 이 버튼은 리버브 효과를 활성화합니다. 이것을 지원하는 파일에서만 작동합니다. - - - Reverb Roomsize: - - - - Reverb Damping: - - - - Reverb Width: - 리버브 너비: - - - Reverb Level: - - Apply chorus (if supported) 코러스 적용 (지원될 경우) - - This button enables the chorus effect. This is useful for cool echo effects, but only works on files that support it. - 이 버튼은 코러스 효과를 활성화합니다. 이것을 지원하는 파일에서만 작동합니다. - - - Chorus Lines: - 코러스 라인: - - - Chorus Level: - 코러스 레벨: - - - Chorus Speed: - 코러스 속도: - - - Chorus Depth: - 코러스 깊이: - Open SoundFont file 사운드폰트 파일 열기 - SoundFont2 Files (*.sf2) - 음성글꼴2 파일 (*.sf2) + Choose patch + + + + Gain: + 이득: + + + Room size: + + + + Damping: + + + + Width: + 너비: + + + Level: + + + + Voices: + + + + Speed: + 속도: + + + Depth: + + + + SoundFont Files (*.sf2 *.sf3) + sfxrInstrument - Wave Form + Wave 파형 sidInstrument - - Cutoff - 컷오프 - Resonance 공명 @@ -9691,22 +8900,26 @@ This chip was used in the Commodore 64 computer. Voice 3 off - + Volume - 볼륨 + 음량 Chip model 칩 모델 + + Cutoff frequency + 차단 주파수 + sidInstrumentView Volume: - 볼륨: + 음량: Resonance: @@ -9716,89 +8929,37 @@ This chip was used in the Commodore 64 computer. Cutoff frequency: 차단 주파수: - - High-Pass filter - 하이패스 필터 - - - Band-Pass filter - 밴드패스 필터 - - - Low-Pass filter - 로우패스 필터 - - - Voice3 Off - - MOS6581 SID - + MOS6581 SID MOS8580 SID - + MOS8580 SID Attack: - - - - Attack rate determines how rapidly the output of Voice %1 rises from zero to peak amplitude. - + Decay: - 감쇄: - - - Decay rate determines how rapidly the output falls from the peak amplitude to the selected Sustain level. - + 감쇠: Sustain: - - - - Output of Voice %1 will remain at the selected Sustain amplitude as long as the note is held. - + Release: - - - - The output of of Voice %1 will fall from Sustain amplitude to zero amplitude at the selected Release rate. - + Pulse Width: - - - - The Pulse Width resolution allows the width to be smoothly swept with no discernable stepping. The Pulse waveform on Oscillator %1 must be selected to have any audible effect. - + 펄스 폭: Coarse: - - - - The Coarse detuning allows to detune Voice %1 one octave up or down. - - - - Pulse Wave - 펄스파 - - - Triangle Wave - 삼각파 - - - SawTooth - 톱니파 + Noise @@ -9808,45 +8969,61 @@ This chip was used in the Commodore 64 computer. Sync 동기화 - - Sync synchronizes the fundamental frequency of Oscillator %1 with the fundamental frequency of Oscillator %2 producing "Hard Sync" effects. - - - - Ring-Mod - 링-모듈레이션 - - - Ring-mod replaces the Triangle Waveform output of Oscillator %1 with a "Ring Modulated" combination of Oscillators %1 and %2. - - Filtered 필터 - - When Filtered is on, Voice %1 will be processed through the Filter. When Filtered is off, Voice %1 appears directly at the output, and the Filter has no effect on it. - - Test 테스트 - Test, when set, resets and locks Oscillator %1 at zero until Test is turned off. - + High-pass filter + + + + Band-pass filter + + + + Low-pass filter + + + + Voice 3 off + + + + Pulse wave + 펄스파 + + + Triangle wave + 삼각파 + + + Saw wave + 톱니파 + + + Ring modulation + + + + Pulse width: + 펄스 폭: stereoEnhancerControlDialog - - WIDE - 넓게 - Width: 너비: + + WIDTH + 너비 + stereoEnhancerControls @@ -9859,19 +9036,19 @@ This chip was used in the Commodore 64 computer. stereoMatrixControlDialog Left to Left Vol: - 왼쪽에서 왼쪽 볼륨: + 왼쪽에서 왼쪽 음량: Left to Right Vol: - 왼쪽에서 오른쪽 볼륨: + 왼쪽에서 오른쪽 음량: Right to Left Vol: - 오른쪽에서 왼쪽 볼륨: + 오른쪽에서 왼쪽 음량: Right to Right Vol: - 오른쪽에서 오른쪽 볼륨: + 오른쪽에서 오른쪽 음량: @@ -9893,6 +9070,19 @@ This chip was used in the Commodore 64 computer. 오른쪽에서 오른쪽 + + testcontext + + test string + + + + test plural %n + + + + + vestigeInstrument @@ -9900,7 +9090,7 @@ This chip was used in the Commodore 64 computer. 플러그인 읽는 중 - Please wait while loading VST-plugin... + Please wait while loading the VST plugin... VST 플러그인을 읽을 동안 잠시 기다려 주세요... @@ -9908,170 +9098,74 @@ This chip was used in the Commodore 64 computer. vibed String %1 volume - %1번 스트링 볼륨 + %1번 현 음량 String %1 stiffness - + Pick %1 position - + Pickup %1 position - - - - Pan %1 - %1번 패닝 - - - Detune %1 - - - - Fuzziness %1 - - - - Length %1 - %1번 길이 + 픽업 %1 위치 Impulse %1 - + - Octave %1 - 옥타브 %1 + String %1 panning + String %1 패닝 + + + String %1 detune + + + + String %1 fuzziness + + + + String %1 length + %1번 현 길이 + + + String %1 + %1번 현 vibedView - - Volume: - 볼륨: - - - The 'V' knob sets the volume of the selected string. - - String stiffness: - - - - The 'S' knob sets the stiffness of the selected string. The stiffness of the string affects how long the string will ring out. The lower the setting, the longer the string will ring. - + Pick position: - - - - The 'P' knob sets the position where the selected string will be 'picked'. The lower the setting the closer the pick is to the bridge. - + Pickup position: - - - - The 'PU' knob sets the position where the vibrations will be monitored for the selected string. The lower the setting, the closer the pickup is to the bridge. - - - - Pan: - 패닝: - - - The Pan knob determines the location of the selected string in the stereo field. - - - - Detune: - - - - The Detune knob modifies the pitch of the selected string. Settings less than zero will cause the string to sound flat. Settings greater than zero will cause the string to sound sharp. - - - - Fuzziness: - - - - The Slap knob adds a bit of fuzz to the selected string which is most apparent during the attack, though it can also be used to make the string sound more 'metallic'. - - - - Length: - 길이: - - - The Length knob sets the length of the selected string. Longer strings will both ring longer and sound brighter, however, they will also eat up more CPU cycles. - - - - Impulse or initial state - - - - The 'Imp' selector determines whether the waveform in the graph is to be treated as an impulse imparted to the string by the pick or the initial state of the string. - + 픽업 위치: Octave 옥타브 - - The Octave selector is used to choose which harmonic of the note the string will ring at. For example, '-2' means the string will ring two octaves below the fundamental, 'F' means the string will ring at the fundamental, and '6' means the string will ring six octaves above the fundamental. - - Impulse Editor Impulse 편집기 - - The waveform editor provides control over the initial state or impulse that is used to start the string vibrating. The buttons to the right of the graph will initialize the waveform to the selected type. The '?' button will load a waveform from a file--only the first 128 samples will be loaded. - -The waveform can also be drawn in the graph. - -The 'S' button will smooth the waveform. - -The 'N' button will normalize the waveform. - - - - Vibed models up to nine independently vibrating strings. The 'String' selector allows you to choose which string is being edited. The 'Imp' selector chooses whether the graph represents an impulse or the initial state of the string. The 'Octave' selector chooses which harmonic the string should vibrate at. - -The graph allows you to control the initial state or impulse used to set the string in motion. - -The 'V' knob controls the volume. The 'S' knob controls the string's stiffness. The 'P' knob controls the pick position. The 'PU' knob controls the pickup position. - -'Pan' and 'Detune' hopefully don't need explanation. The 'Slap' knob adds a bit of fuzz to the sound of the string. - -The 'Length' knob controls the length of the string. - -The LED in the lower right corner of the waveform editor determines whether the string is active in the current instrument. - - Enable waveform 파형 활성화 - - Click here to enable/disable waveform. - 클릭하여 파형 활성화/비활성화. - String - - - - The String selector is used to choose which string the controls are editing. A Vibed instrument can contain up to nine independently vibrating strings. The LED in the lower right corner of the waveform editor indicates whether the selected string is active. - + Sine wave @@ -10090,79 +9184,75 @@ The LED in the lower right corner of the waveform editor determines whether the 사각파 - White noise wave + String volume: + + + + String panning: + + + + String detune: + + + + String fuzziness: + + + + String length: + + + + Impulse + + + + Enable/disable string + + + + White noise 화이트 노이즈 - User defined wave - 사용자 정의 파형 + User-defined wave + 사용자 지정 파형 - Smooth - 부드럽게 + Smooth waveform + 파형을 부드럽게 - Click here to smooth waveform. - 클릭하여 파형을 부드럽게 합니다. - - - Normalize - 규격화 - - - Click here to normalize waveform. - 클릭하여 파형을 규격화합니다. - - - Use a sine-wave for current oscillator. - 이 오실레이터에 사인파 사용 - - - Use a triangle-wave for current oscillator. - 이 오실레이터에 삼각파 사용 - - - Use a saw-wave for current oscillator. - 이 오실레이터에 톱니파 사용 - - - Use a square-wave for current oscillator. - 이 오실레이터에 사각파 사용 - - - Use white-noise for current oscillator. - - - - Use a user-defined waveform for current oscillator. - 이 오실레이터에 사용자 지정 파형 사용 + Normalize waveform + voiceObject Voice %1 pulse width - + 소리 %1 펄스 폭 Voice %1 attack - + Voice %1 decay - + Voice %1 sustain - + Voice %1 release - + Voice %1 coarse detuning - + Voice %1 wave shape @@ -10203,45 +9293,29 @@ The LED in the lower right corner of the waveform editor determines whether the Output gain: 출력 이득: - - Reset waveform - 파형 초기화 - - - Click here to reset the wavegraph back to default - 클릭하여 기본 그래프로 초기화 - - - Smooth waveform - 파형을 부드럽게 - - - Click here to apply smoothing to wavegraph - - - - Increase graph amplitude by 1dB - - - - Click here to increase wavegraph amplitude by 1dB - - - - Decrease graph amplitude by 1dB - - - - Click here to decrease wavegraph amplitude by 1dB - - Clip input - + 입력 신호 클리핑 - Clip input signal to 0dB - + Reset wavegraph + 그래프 초기화 + + + Smooth wavegraph + 그래프를 부드럽게 + + + Increase wavegraph amplitude by 1 dB + + + + Decrease wavegraph amplitude by 1 dB + + + + Clip input signal to 0 dB + @@ -10255,4 +9329,4 @@ The LED in the lower right corner of the waveform editor determines whether the 출력 이득 - \ No newline at end of file + diff --git a/data/locale/pl.ts b/data/locale/pl.ts index 5d9cc51cd..4214718af 100644 --- a/data/locale/pl.ts +++ b/data/locale/pl.ts @@ -3108,7 +3108,7 @@ Możesz usunąć i przenieść kanały FX w menu kontekstowym, które jest dost VELOCITY - GŁOŚNOŚĆ UDERZENIA + PRĘDKOŚĆ ENABLE MIDI OUTPUT @@ -10321,4 +10321,4 @@ Kontrolka LED w prawym dolnym rogu edytora kształtu fali pokazuje, czy wybrana Wzmocnienie wyścia - \ No newline at end of file + diff --git a/data/locale/pt.ts b/data/locale/pt.ts index d9c3a7cb2..f1a2386f3 100644 --- a/data/locale/pt.ts +++ b/data/locale/pt.ts @@ -80,7 +80,7 @@ Esteban Viveros LEFT - ESQUERDA + LEFT Left gain: @@ -88,7 +88,7 @@ Esteban Viveros RIGHT - DIREITA + RIGHT Right gain: @@ -705,11 +705,11 @@ Esteban Viveros BitcrushControlDialog IN - DENTRO + IN OUT - FORA + OUT GAIN @@ -3099,7 +3099,7 @@ You can remove and move FX channels in the context menu, which is accessed by ri VELOCITY - INTENSIDADE + VELOCITY ENABLE MIDI OUTPUT @@ -7936,7 +7936,7 @@ Por favor certifique-se que você tem permissões de leitura para o arquivo e pa RELEASE - LANÇAMENTO + RELEASE Peak release time: diff --git a/data/locale/ru.ts b/data/locale/ru.ts index 1bc94ca92..f717d598d 100644 --- a/data/locale/ru.ts +++ b/data/locale/ru.ts @@ -2,30 +2,62 @@ AboutDialog + About LMMS О программе LMMS + + LMMS + ЛММС + + + Version %1 (%2/%3, Qt %4, %5) Версия %1 (%2/%3, Qt %4, %5) + About Подробнее + LMMS - easy music production for everyone LMMS - лёгкое создание музыки для всех + + Copyright © %1 + Все права защищены © %1 + + + + <html><head/><body><p><a href="https://lmms.io"><span style=" text-decoration: underline; color:#0000ff;">https://lmms.io</span></a></p></body></html> + <html><head/><body><p><a href="https://lmms.io"><span style=" text-decoration: underline; color:#0000ff;">https://lmms.io</span></a></p></body></html> + + + Authors Авторы + + Involved + Участники + + + + Contributors ordered by number of commits: + Разработчики сортированные по числу коммитов: + + + Translation Перевод + Current language not translated (or native English). If you're interested in translating LMMS in another language or want to improve existing translations, you're welcome to help us! Simply contact the maintainer! @@ -36,61 +68,50 @@ Alexey Kouznetsov <alexey/dot/kouznetsov/at/gmail/dot/com> Oe Ai <oeai/at/symbiants/dot/com> + License Лицензия - - LMMS - ЛММС - - - Involved - Участники - - - Contributors ordered by number of commits: - Разработчики сортированные по числу коммитов: - - - Copyright © %1 - Все права защищены © %1 - - - <html><head/><body><p><a href="https://lmms.io"><span style=" text-decoration: underline; color:#0000ff;">https://lmms.io</span></a></p></body></html> - <html><head/><body><p><a href="https://lmms.io"><span style=" text-decoration: underline; color:#0000ff;">https://lmms.io</span></a></p></body></html> - AmplifierControlDialog + VOL ГРОМ + Volume: Громкость: + PAN БАЛ + Panning: Баланс: + LEFT Лево + Left gain: Лево мощность: + RIGHT Право + Right gain: Право мощность: @@ -98,18 +119,22 @@ Oe Ai <oeai/at/symbiants/dot/com> AmplifierControls + Volume Громкость + Panning Баланс + Left gain Лево мощн + Right gain Право мощн @@ -117,10 +142,12 @@ Oe Ai <oeai/at/symbiants/dot/com> AudioAlsaSetupWidget + DEVICE УСТРОЙСТВО + CHANNELS КАНАЛЫ @@ -128,78 +155,98 @@ Oe Ai <oeai/at/symbiants/dot/com> AudioFileProcessorView + Open other sample Открыть другую запись + Click here, if you want to open another audio-file. A dialog will appear where you can select your file. Settings like looping-mode, start and end-points, amplify-value, and so on are not reset. So, it may not sound like the original sample. Нажмите здесь, чтобы открыть другой звуковой файл. В новом окне диалога вы сможете выбрать нужный файл. Такие настройки, как режим повтора, точки начала/конца, усиление и прочие не сбросятся, поэтому звучание может отличаться от оригинала. + Reverse sample Отзеркалить запись + If you enable this button, the whole sample is reversed. This is useful for cool effects, e.g. a reversed crash. Если включить эту кнопку, вся запись пойдёт в обратную сторону, это удобно для крутых эффектов, типа обратного грохота. - Amplify: - Усиление: - - - With this knob you can set the amplify ratio. When you set a value of 100% your sample isn't changed. Otherwise it will be amplified up or down (your actual sample-file isn't touched!) - Эта ручка задаёт коэффициент усиления. При значении 100% исходный звук не меняется, в противном случае ― он будет ослаблен или усилен. (Обратите внимание, что исходная запись при этом останется нетронутой.) - - - Startpoint: - Начало: - - - Endpoint: - Конец: - - - Continue sample playback across notes - Продолжить воспроизведение записи по нотам - - - Enabling this option makes the sample continue playing across different notes - if you change pitch, or the note length stops before the end of the sample, then the next note played will continue where it left off. To reset the playback to the start of the sample, insert a note at the bottom of the keyboard (< 20 Hz) - Включение этой опции продолжит воспроизведение записи по разным нотам - если изменить ускорение или длительность ноты остановится до конца записи, то со следующей ноты запись продолжится там, где остановилась, чтобы сбросить воспроизвдение на начало записи, вставьте ноту внизу у клавиш (<20 Гц) - - + Disable loop Отключить петлю + This button disables looping. The sample plays only once from start to end. - Эта кнопка отключает петлю (loop-цикл). Запись проигрывается только один раз от начала до конца. + Эта кнопка отключает зацикливание (loop-цикл). Запись проигрывается только один раз от начала до конца. + + Enable loop Включить петлю + This button enables forwards-looping. The sample loops between the end point and the loop point. Эта кнопка включает переднюю петлю. Сэмпл кольцуется между конечной точкой и точкой петли. + This button enables ping-pong-looping. The sample loops backwards and forwards between the end point and the loop point. Эта кнопка включает пинг-понг петлю. Сэмпл кольцуется обратно и вперёд между конечной точкой и точкой петли. + + Continue sample playback across notes + Продолжить воспроизведение записи по нотам + + + + Enabling this option makes the sample continue playing across different notes - if you change pitch, or the note length stops before the end of the sample, then the next note played will continue where it left off. To reset the playback to the start of the sample, insert a note at the bottom of the keyboard (< 20 Hz) + Включение этой опции продолжит воспроизведение записи по разным нотам - если изменить ускорение или длительность ноты остановится до конца записи, то со следующей ноты запись продолжится там, где остановилась, чтобы сбросить воспроизвдение на начало записи, вставьте ноту внизу у клавиш (<20 Гц) + + + + Amplify: + Усиление: + + + + With this knob you can set the amplify ratio. When you set a value of 100% your sample isn't changed. Otherwise it will be amplified up or down (your actual sample-file isn't touched!) + Эта ручка задаёт коэффициент усиления. При значении 100% исходный звук не меняется, в противном случае ― он будет ослаблен или усилен. (Обратите внимание, что исходная запись при этом останется нетронутой.) + + + + Startpoint: + Начало: + + + With this knob you can set the point where AudioFileProcessor should begin playing your sample. Этим регулятором можно установить точку где АудиоФайлПроцессор должен начать воспроизведение сэмпла. + + Endpoint: + Конец: + + + With this knob you can set the point where AudioFileProcessor should stop playing your sample. Этот регулятор устанавливает точку в которой АудиоФайлПроцессор должен перестать воспроизвдение сэмпла. + Loopback point: Точка возврата петли: + With this knob you can set the point where the loop starts. Этот регулятор ставит точку начала петли. @@ -207,6 +254,7 @@ Oe Ai <oeai/at/symbiants/dot/com> AudioFileProcessorWaveView + Sample length: Длина записи: @@ -214,26 +262,32 @@ Oe Ai <oeai/at/symbiants/dot/com> AudioJack + JACK client restarted JACK-клиент перезапущен + LMMS was kicked by JACK for some reason. Therefore the JACK backend of LMMS has been restarted. You will have to make manual connections again. LMMS не был подключен к JACK по какой-то причине, поэтому LMMS подключение к JACK было перезапущено. Вам придётся заново вручную создать соединения. + JACK server down JACK-сервер не доступен + The JACK server seems to have been shutdown and starting a new instance failed. Therefore LMMS is unable to proceed. You should save your project and restart JACK and LMMS. Возможно JACK-сервер был выключен и запуск нового процесса не удался, поэтому ЛММС не может продолжить работу. Вам следует сохранить проект и перезапустить JACK и LMMS. + CLIENT-NAME ИМЯ КЛИЕНТА + CHANNELS КАНАЛЫ @@ -241,10 +295,12 @@ Oe Ai <oeai/at/symbiants/dot/com> AudioOss::setupWidget + DEVICE УСТРОЙСТВО + CHANNELS КАНАЛЫ @@ -252,10 +308,12 @@ Oe Ai <oeai/at/symbiants/dot/com> AudioPortAudio::setupWidget + BACKEND УПРАВЛЕНИЕ + DEVICE УСТРОЙСТВО @@ -263,10 +321,12 @@ Oe Ai <oeai/at/symbiants/dot/com> AudioPulseAudio::setupWidget + DEVICE УСТРОЙСТВО + CHANNELS КАНАЛЫ @@ -274,6 +334,7 @@ Oe Ai <oeai/at/symbiants/dot/com> AudioSdl::setupWidget + DEVICE УСТРОЙСТВО @@ -281,10 +342,12 @@ Oe Ai <oeai/at/symbiants/dot/com> AudioSndio::setupWidget + DEVICE УСТРОЙСТВО + CHANNELS КАНАЛЫ @@ -292,10 +355,12 @@ Oe Ai <oeai/at/symbiants/dot/com> AudioSoundIo::setupWidget + BACKEND БЭКЕНД + DEVICE УСТРОЙСТВО @@ -303,61 +368,75 @@ Oe Ai <oeai/at/symbiants/dot/com> AutomatableModel + &Reset (%1%2) &R Сбросить (%1%2) + &Copy value (%1%2) &C Копировать значение (%1%2) + &Paste value (%1%2) &P Вставить значение (%1%2) + Edit song-global automation Изменить глоабльную автоматизацию композиции - Connected to %1 - Подсоединено к %1 - - - Connected to controller - Подсоединено к контроллеру - - - Edit connection... - Настроить соединение... - - - Remove connection - Удалить соединение - - - Connect to controller... - Соединить с контроллером... - - + Remove song-global automation Убрать глобальную автоматизацию композиции + Remove all linked controls Убрать всё присоединенное управление + + + Connected to %1 + Подсоединено к %1 + + + + Connected to controller + Подсоединено к контроллеру + + + + Edit connection... + Настроить соединение... + + + + Remove connection + Удалить соединение + + + + Connect to controller... + Соединить с контроллером... + AutomationEditor + Please open an automation pattern with the context menu of a control! Откройте редатор автоматизации через контекстное меню регулятора! + Values copied Значения скопированы + All selected values were copied to the clipboard. Все выбранные значения скопированы в буфер обмена. @@ -365,159 +444,194 @@ Oe Ai <oeai/at/symbiants/dot/com> AutomationEditorWindow + Play/pause current pattern (Space) Игра/Пауза текущей мелодии (Пробел) + Click here if you want to play the current pattern. This is useful while editing it. The pattern is automatically looped when the end is reached. Нажмите здесь чтобы проиграть текущую мелодию. Это может пригодиться при его редактировании. Мелодия автоматически закольцуется при достижении конца. + Stop playing of current pattern (Space) Остановить воспроизведение текущей мелодии (Пробел) + Click here if you want to stop playing of the current pattern. Нажмите здесь, если вы хотите остановить воспроизведение текущей мелодии. + + Edit actions + Правка: + + + Draw mode (Shift+D) Режим рисования (Shift+D) + Erase mode (Shift+E) Режим стирания (Shift-E) + Flip vertically Перевернуть вертикально + Flip horizontally Перевернуть горизонтально + Click here and the pattern will be inverted.The points are flipped in the y direction. Нажмите здесь и мелодия перевернётся. Точки переворачиваются в Y направлении. + Click here and the pattern will be reversed. The points are flipped in the x direction. Нажмите здесь и мелодия перевернётся в направлении X. + Click here and draw-mode will be activated. In this mode you can add and move single values. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. При нажатии на эту кнопку активируется режим рисования нот, в нём вы можете добавлять/перемещать и изменять длительность одиночных нот. Это основной режим и используется большую часть времени. Для включения этого режима можно использовать комбинацию клавиш Shift+D. + Click here and erase-mode will be activated. In this mode you can erase single values. You can also press 'Shift+E' on your keyboard to activate this mode. При нажатии на эту кнопку активируется режим стирания. В этом режиме вы можете стирать ноты по одной. Для включения этого режима можно использовать комбинацию клавиш Shift+E. - Discrete progression - Дискретная прогрессия - - - Linear progression - Линейная прогрессия - - - Cubic Hermite progression - Кубическая Эрмитова прогрессия - - - Tension value for spline - Величина напряжения для сплайна - - - A higher tension value may make a smoother curve but overshoot some values. A low tension value will cause the slope of the curve to level off at each control point. - Более высокое напряжение может сделать кривую более мягкой, но перегрузит некоторые величины. Низкое напряжение сделает наклон кривой ниже в каждой контрольной точке. - - - Click here to choose discrete progressions for this automation pattern. The value of the connected object will remain constant between control points and be set immediately to the new value when each control point is reached. - Выбор дискретной прогрессии для этого шаблона автоматизации. Кол-во подсоединенных объектов будет оставаться постоянным между управляющими точками и будет установлено на новое значение сразу по достижении каждой управляющей точки. - - - Click here to choose linear progressions for this automation pattern. The value of the connected object will change at a steady rate over time between control points to reach the correct value at each control point without a sudden change. - Выбор линейной прогрессии для этого шаблона автоматизации. Кол-во подсоединенных объектов будет меняться с постоянной скоростью во времени между управляющими точками для достижения точного значения в каждой управляющей точки без внезапных изменений. - - - Click here to choose cubic hermite progressions for this automation pattern. The value of the connected object will change in a smooth curve and ease in to the peaks and valleys. - Кубическая Эрмитова прогрессия для этого шаблона автоматизации. Кол-во подсоединенных объектов изменится по сглаженной кривой и смягчится на пиках и спадах. - - - Cut selected values (%1+X) - Вырезать выбранные ноты (%1+X) - - - Copy selected values (%1+C) - Копировать выбранные ноты в буфер (%1+C) - - - Paste values from clipboard (%1+V) - Вставить запомненные значения (%1+V) - - - Click here and selected values will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. - При нажатии на эту кнопку выделеные ноты будут вырезаны в буфер. Позже вы можете вставить их в любое место любой мелодии с помощью кнопки "Вставить". - - - Click here and selected values will be copied into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. - При нажатии на эту кнопку выделеные ноты будут скопированы в буфер. Позже вы можете вставить их в любое место любой мелодии с помощью кнопки "Вставить". - - - Click here and the values from the clipboard will be pasted at the first visible measure. - При нажатии на эту кнопку ноты из буфера будут вставлены в первый видимый такт. - - - Tension: - Напряжение: - - - Automation Editor - no pattern - Редактор автоматизаци — нет шаблона - - - Automation Editor - %1 - Редактор автоматизации — %1 - - - Edit actions - Правка: - - + Interpolation controls Управление интерполяцией - Timeline controls - Управление временем + + Discrete progression + Дискретная прогрессия + + Linear progression + Линейная прогрессия + + + + Cubic Hermite progression + Кубическая Эрмитова прогрессия + + + + Tension value for spline + Величина напряжения для сплайна + + + + A higher tension value may make a smoother curve but overshoot some values. A low tension value will cause the slope of the curve to level off at each control point. + Более высокое напряжение может сделать кривую более мягкой, но перегрузит некоторые величины. Низкое напряжение сделает наклон кривой ниже в каждой контрольной точке. + + + + Click here to choose discrete progressions for this automation pattern. The value of the connected object will remain constant between control points and be set immediately to the new value when each control point is reached. + Выбор дискретной прогрессии для этого шаблона автоматизации. Кол-во подсоединенных объектов будет оставаться постоянным между управляющими точками и будет установлено на новое значение сразу по достижении каждой управляющей точки. + + + + Click here to choose linear progressions for this automation pattern. The value of the connected object will change at a steady rate over time between control points to reach the correct value at each control point without a sudden change. + Выбор линейной прогрессии для этого шаблона автоматизации. Кол-во подсоединенных объектов будет меняться с постоянной скоростью во времени между управляющими точками для достижения точного значения в каждой управляющей точки без внезапных изменений. + + + + Click here to choose cubic hermite progressions for this automation pattern. The value of the connected object will change in a smooth curve and ease in to the peaks and valleys. + Кубическая Эрмитова прогрессия для этого шаблона автоматизации. Кол-во подсоединенных объектов изменится по сглаженной кривой и смягчится на пиках и спадах. + + + + Tension: + Напряжение: + + + + Cut selected values (%1+X) + Вырезать выбранные ноты (%1+X) + + + + Copy selected values (%1+C) + Копировать выбранные ноты в буфер (%1+C) + + + + Paste values from clipboard (%1+V) + Вставить запомненные значения (%1+V) + + + + Click here and selected values will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. + При нажатии на эту кнопку выделеные ноты будут вырезаны в буфер. Позже вы можете вставить их в любое место любой мелодии с помощью кнопки "Вставить". + + + + Click here and selected values will be copied into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. + При нажатии на эту кнопку выделеные ноты будут скопированы в буфер. Позже вы можете вставить их в любое место любой мелодии с помощью кнопки "Вставить". + + + + Click here and the values from the clipboard will be pasted at the first visible measure. + При нажатии на эту кнопку ноты из буфера будут вставлены в первый видимый такт. + + + Zoom controls Приблизить управление + Quantization controls Управление квантованием - Model is already connected to this pattern. - Модель уже подключена к этому шаблону. - - + Quantization Квантование + Quantization. Sets the smallest step size for the Automation Point. By default this also sets the length, clearing out other points in the range. Press <Ctrl> to override this behaviour. + + + + Automation Editor - no pattern + Редактор автоматизаци — нет шаблона + + + + + Automation Editor - %1 + Редактор автоматизации — %1 + + + + Model is already connected to this pattern. + Модель уже подключена к этому шаблону. + AutomationPattern + Drag a control while pressing <%1> Тяните контроль удерживая <%1> @@ -525,42 +639,57 @@ Oe Ai <oeai/at/symbiants/dot/com> AutomationPatternView + + double-click to open this pattern in automation editor + Дважды щёлкните мышью чтобы настроить автоматизацию этого шаблона + + + Open in Automation editor Открыть в редакторе автоматизации + Clear Очистить + Reset name Сбросить название + Change name Переименовать - %1 Connections - Соединения %1 - - - Disconnect "%1" - Отсоединить «%1» - - + Set/clear record Установить/очистить запись + Flip Vertically (Visible) Перевернуть вертикально (Видимое) + Flip Horizontally (Visible) Перевернуть горизонтально (Видимое) + + %1 Connections + Соединения %1 + + + + Disconnect "%1" + Отсоединить «%1» + + + Model is already connected to this pattern. Модель уже подключена к этому шаблону. @@ -568,6 +697,7 @@ Oe Ai <oeai/at/symbiants/dot/com> AutomationTrack + Automation track Дорожка автоматизации @@ -575,77 +705,95 @@ Oe Ai <oeai/at/symbiants/dot/com> BBEditor + Beat+Bassline Editor Ритм+Бас Редактор + Play/pause current beat/bassline (Space) Игра/пауза текущей линии ритма/баса (<Space>) + Stop playback of current beat/bassline (Space) Остановить воспроизведение текущей линии ритм-баса (ПРОБЕЛ) + Click here to play the current beat/bassline. The beat/bassline is automatically looped when its end is reached. Нажмите чтобы проиграть текущую линию ритм-баса. Она будет закольцована по достижении окончания. + Click here to stop playing of current beat/bassline. Остановить воспроизведение (Пробел). - Add beat/bassline - Добавить ритм/бас - - - Add automation-track - Добавить дорожку автоматизации - - - Remove steps - Убрать такты - - - Add steps - Добавить такты - - + Beat selector Выбор бита + Track and step actions - + Действия для дорожки или ее части - Clone Steps - Клонировать такты + + Add beat/bassline + Добавить ритм/бас + Add sample-track Добавить дорожку записи + + + Add automation-track + Добавить дорожку автоматизации + + + + Remove steps + Убрать такты + + + + Add steps + Добавить такты + + + + Clone Steps + Клонировать такты + BBTCOView + Open in Beat+Bassline-Editor Открыть в редакторе ритм + баса + Reset name Сбросить название + Change name Переименовать + Change color Изменить цвет + Reset color to default Установить цвет по умолчанию @@ -653,10 +801,12 @@ Oe Ai <oeai/at/symbiants/dot/com> BBTrack + Beat/Bassline %1 Ритм-Бас Линия %1 + Clone of %1 Копия %1 @@ -664,26 +814,32 @@ Oe Ai <oeai/at/symbiants/dot/com> BassBoosterControlDialog + FREQ ЧАСТ + Frequency: Частота: + GAIN МОЩ + Gain: Мощность: + RATIO ОТН + Ratio: Отношение: @@ -691,14 +847,17 @@ Oe Ai <oeai/at/symbiants/dot/com> BassBoosterControls + Frequency Частота + Gain Мощность + Ratio Отношение @@ -706,89 +865,111 @@ Oe Ai <oeai/at/symbiants/dot/com> BitcrushControlDialog + IN ВХОД + OUT ВЫХОД + + GAIN МОЩ + Input Gain: Входная мощность: - Input Noise: - Входной шум: - - - Output Gain: - Выходная мощность: - - - CLIP - СРЕЗ - - - Output Clip: - - - - Rate Enabled - Частота выборки включена - - - Enable samplerate-crushing - - - - Depth Enabled - Глубина включена - - - Enable bitdepth-crushing - - - - Sample rate: - Частота сэмплирования: - - - Stereo difference: - Стерео разница: - - - Levels: - Уровни: - - + NOISE Шум + + Input Noise: + Входной шум: + + + + Output Gain: + Выходная мощность: + + + + CLIP + СРЕЗ + + + + Output Clip: + Выходная обрезка: + + + + Rate Enabled + Частота выборки включена + + + + Enable samplerate-crushing + Включить дробление частоты дискретизации + + + + Depth Enabled + Глубина включена + + + + Enable bitdepth-crushing + Включить дробление битовой глубины + + + FREQ FREQ + + Sample rate: + Частота сэмплирования: + + + STEREO СТЕРЕО + + Stereo difference: + Стерео разница: + + + QUANT - + КВАНТ + + + + Levels: + Уровни: CaptionMenu + &Help &H Справка + Help (not available) Справка (не доступна) @@ -796,10 +977,12 @@ Oe Ai <oeai/at/symbiants/dot/com> CarlaInstrumentView + Show GUI Показать интерфейс + Click here to show or hide the graphical user interface (GUI) of Carla. Нажмите сюда, чтобы показать или скрыть графический интерфейс Карла. @@ -807,6 +990,7 @@ Oe Ai <oeai/at/symbiants/dot/com> Controller + Controller %1 Контроллер %1 @@ -814,58 +998,73 @@ Oe Ai <oeai/at/symbiants/dot/com> ControllerConnectionDialog + Connection Settings Параметры соединения + MIDI CONTROLLER MIDI-КОНТРОЛЛЕР + Input channel Канал ввода + CHANNEL КАНАЛ + Input controller Контроллер ввода + CONTROLLER КОНТРОЛЛЕР + + Auto Detect Автоопределение + MIDI-devices to receive MIDI-events from Устройства MiDi для приёма событий + USER CONTROLLER ПОЛЬЗ. КОНТРОЛЛЕР + MAPPING FUNCTION ПЕРЕОПРЕДЕЛЕНИЕ + OK ОК + Cancel Отменить + LMMS LMMS + Cycle Detected. Обнаружен цикл. @@ -873,18 +1072,22 @@ Oe Ai <oeai/at/symbiants/dot/com> ControllerRackView + Controller Rack Рэка контроллеров + Add Добавить + Confirm Delete Подтвердить удаление + Confirm delete? There are existing connection(s) associated with this controller. There is no way to undo. Подтверждаете удаление? Есть возможные соединения с этим контроллером, возврата не будет. @@ -892,116 +1095,143 @@ Oe Ai <oeai/at/symbiants/dot/com> ControllerView + Controls Управление + Controllers are able to automate the value of a knob, slider, and other controls. Контроллеры могут автоматизировать изменения значений регуляторов, ползунков и прочего управления. + Rename controller Переименовать контроллер + Enter the new name for this controller Введите новое название для контроллера + + LFO + LFO + + + &Remove this controller Убрать этот контроллер + Re&name this controller Переименовать этот контроллер - - LFO - LFO - CrossoverEQControlDialog + Band 1/2 Crossover: - + Полоса 1/2 кроссовер: + Band 2/3 Crossover: - + Полоса 2/3 кроссовер: + Band 3/4 Crossover: - + Полоса 3/4 кроссовер: + Band 1 Gain: - + Полоса 1 усиление: + Band 2 Gain: - + Полоса 2 усиление: + Band 3 Gain: - + Полоса 3 усиление: + Band 4 Gain: - + Полоса 4 усиление: + Band 1 Mute - + Полоса 1 выключена + Mute Band 1 - + Заглушить полосу 1 + Band 2 Mute - + Полоса 2 выключена + Mute Band 2 - + Заглушить полосу 2 + Band 3 Mute - + Полоса 3 заглушена + Mute Band 3 - + Заглушить полосу 3 + Band 4 Mute - + Полоса 4 заглушена + Mute Band 4 - + Заглушить полосу 4 DelayControls + Delay Samples Задержка сэмплов + Feedback Возврат + Lfo Frequency Частота LFO + Lfo Amount Объём LFO + Output gain Выходная мощность @@ -1009,270 +1239,362 @@ Oe Ai <oeai/at/symbiants/dot/com> DelayControlsDialog - Lfo Amt - - - - Delay Time - Время задержки - - - Feedback Amount - Объём возврата: - - - Lfo - Lfo - - - Out Gain - Выходная мощность - - - Gain - Усиление - - + DELAY ЗАДЕРЖ + + Delay Time + Время задержки + + + FDBK + + Feedback Amount + Объём возврата: + + + RATE ЧАСТ + + Lfo + Lfo + + + AMNT ГЛУБ + + + Lfo Amt + Вел LFO + + + + Out Gain + Выходная мощность + + + + Gain + Усиление + DualFilterControlDialog - Filter 1 enabled - Фильтр 1 включен - - - Filter 2 enabled - Фильтр 2 включен - - - Click to enable/disable Filter 1 - Кликнуть для включения/выключения Фильтра 1 - - - Click to enable/disable Filter 2 - Кликнуть для включения/выключения Фильтра 2 - - + + FREQ FREQ + + Cutoff frequency Срез частот + + RESO RESO + + Resonance Резонанс + + GAIN МОЩ + + Gain УСИЛ + MIX - + МИКС + Mix - + Микс + + + + Filter 1 enabled + Фильтр 1 включен + + + + Filter 2 enabled + Фильтр 2 включен + + + + Click to enable/disable Filter 1 + Кликнуть для включения/выключения Фильтра 1 + + + + Click to enable/disable Filter 2 + Кликнуть для включения/выключения Фильтра 2 DualFilterControls + Filter 1 enabled Фильтр 1 включен + Filter 1 type - + Фильтр 1 тип + Cutoff 1 frequency - + Срез 1 частоты + Q/Resonance 1 + Gain 1 - + Усиление 1 + Mix - + Микс + Filter 2 enabled Фильтр 2 включен + Filter 2 type - + Фильтр 2 тип + Cutoff 2 frequency - + Срез 2 частоты + Q/Resonance 2 + Gain 2 - + Усиление 2 + + LowPass Низ.ЧФ + + HiPass Выс.ЧФ + + BandPass csg Сред.ЧФ csg + + BandPass czpg Сред.ЧФ czpg + + Notch Полосно-заграждающий + + Allpass Все проходят + + Moog Муг + + 2x LowPass 2х Низ.ЧФ + + RC LowPass 12dB RC Низ.ЧФ 12дБ + + RC BandPass 12dB RC Сред.ЧФ 12 дБ + + RC HighPass 12dB RC Выс.ЧФ 12дБ + + RC LowPass 24dB RC Низ.ЧФ 24дБ + + RC BandPass 24dB RC Сред.ЧФ 24дБ + + RC HighPass 24dB RC Выс.ЧФ 24дБ + + Vocal Formant Filter Фильтр Вокальной форманты + + 2x Moog 2x Муг + + SV LowPass SV Низ.ЧФ + + SV BandPass SV Сред.ЧФ + + SV HighPass SV Выс.ЧФ + + SV Notch + + Fast Formant + + Tripole - + Триполи Editor + + Transport controls + Управление транспортом + + + Play (Space) Игра (Пробел) + Stop (Space) Стоп (Пробел) + Record Запись + Record while playing Запись при игре - - Transport controls - Управление транспортом - Effect + Effect enabled Эффект включён + Wet/Dry mix Насыщенность + Gate Шлюз + Decay Затихание @@ -1280,6 +1602,7 @@ Oe Ai <oeai/at/symbiants/dot/com> EffectChain + Effects enabled Эффекты включёны @@ -1287,10 +1610,12 @@ Oe Ai <oeai/at/symbiants/dot/com> EffectRackView + EFFECTS CHAIN ЦЕПЬ ЭФФЕКТОВ + Add effect Добавить эффект @@ -1298,22 +1623,28 @@ Oe Ai <oeai/at/symbiants/dot/com> EffectSelectDialog + Add effect Добавить эффект + + Name Имя + Type Тип + Description Описание + Author Автор @@ -1321,54 +1652,67 @@ Oe Ai <oeai/at/symbiants/dot/com> EffectView + Toggles the effect on or off. Вкл/выкл эффект. + On/Off Вкл/Выкл + W/D - НАСЫЩ + + Wet Level: Уровень насыщенности: + The Wet/Dry knob sets the ratio between the input signal and the effect signal that forms the output. Регулятор насыщенности определяет долю обработанного сигнала, которая будет на выходе. + DECAY - ЗАТИХ + + Time: Время: + The Decay knob controls how many buffers of silence must pass before the plugin stops processing. Smaller values will reduce the CPU overhead but run the risk of clipping the tail on delay and reverb effects. Decay (затихание) управляет количеством буферов тишины, которые должны пройти до конца работы плагина. Меньшие величины снижают перегрузку процессора, но вознкает риск появления потрескивания или подрезания в хвосте на передержке (delay) или эхо (reverb) эффектах. + GATE ШЛЮЗ + Gate: Шлюз: + The Gate knob controls the signal level that is considered to be 'silence' while deciding when to stop processing signals. GATE (Шлюз) определяет уровень сигнала, который будет считаться "тишиной" при определении остановки обрабатывания сигналов. + Controls Управление + Effect plugins function as a chained series of effects where the signal will be processed from top to bottom. The On/Off switch allows you to bypass a given plugin at any point in time. @@ -1398,14 +1742,17 @@ Right clicking will bring up a context menu where you can change the order in wh Контекстное меню, вызываемое щелчком правой кнопкой мыши, позволяет менять порядок следования фильтров или удалять их вместе с другими. + Move &up &u Переместить выше + Move &down &d Переместить ниже + &Remove this plugin &R Убрать фильтр @@ -1413,58 +1760,72 @@ Right clicking will bring up a context menu where you can change the order in wh EnvelopeAndLfoParameters + Predelay Задержка + Attack Вступление + Hold Удерживание + Decay Затихание + Sustain Выдержка + Release Убывание + Modulation Модуляция + LFO Predelay Задержка LFO + LFO Attack Вступление LFO + LFO speed Скорость LFO + LFO Modulation Модуляция LFO + LFO Wave Shape Форма сигнала LFO + Freq x 100 ЧАСТ x 100 + Modulate Env-Amount Модулировать огибающую @@ -1472,625 +1833,784 @@ Right clicking will bring up a context menu where you can change the order in wh EnvelopeAndLfoView + + DEL DEL + Predelay: Задержка: + Use this knob for setting predelay of the current envelope. The bigger this value the longer the time before start of actual envelope. Эта ручка определяет задержку огибающей. Чем больше эта величина, тем дольше время до старта текущей огибающей. + + ATT ATT + Attack: Вступление: + Use this knob for setting attack-time of the current envelope. The bigger this value the longer the envelope needs to increase to attack-level. Choose a small value for instruments like pianos and a big value for strings. Эта ручка устанавливает время возрастания для текущей огибающей. Чем больше значение, тем дольше характеристика (н-р, громкость) возрастает до максимума. Для инструменов вроде пианино характерны малые времена нарастания, а для струнных - большие. + HOLD HOLD + Hold: Удержание: + Use this knob for setting hold-time of the current envelope. The bigger this value the longer the envelope holds attack-level before it begins to decrease to sustain-level. Эта ручка устанавливает длительность огибающей. Чем больше значение, тем дольше огибающая держится на наивысшем уровне. + DEC DEC + Decay: - Затихание: + Затухание: + Use this knob for setting decay-time of the current envelope. The bigger this value the longer the envelope needs to decrease from attack-level to sustain-level. Choose a small value for instruments like pianos. Эта ручка устанавливает время спада для текущей огибающей. Чем больше значение, тем дольше огибающая должна сокращаться от вступления до уровня выдержки. Для инструментов вроде пианино следует выбирать небольшие значения. + SUST SUST + Sustain: Выдержка: + Use this knob for setting sustain-level of the current envelope. The bigger this value the higher the level on which the envelope stays before going down to zero. Эта ручка устанавливает уровень выдержки. Чем больше эта величина, тем выше уровень на котором остаётся огибающая, прежде чем опуститься до нуля. + REL REL + Release: Убывание: + Use this knob for setting release-time of the current envelope. The bigger this value the longer the envelope needs to decrease from sustain-level to zero. Choose a big value for soft instruments like strings. Эта ручка устанавливает время убывания для текущей огибающей. Чем больше значение, тем дольше характеристика (н-р, громкость) уменьшается от уровня выдержки до нуля. Для струнных инструментов следует выбирать большие значения. + + AMT AMT + + Modulation amount: Глубина модуляции: + Use this knob for setting modulation amount of the current envelope. The bigger this value the more the according size (e.g. volume or cutoff-frequency) will be influenced by this envelope. Эта ручка устанавливает глубину модуляции для текущей огибающей. Чем больше значение, тем в большей степени выбранная характеристика (н-р, громкость или частота среза) будет зависеть от этой огибающей. + LFO predelay: Пред. задержка LFO: + Use this knob for setting predelay-time of the current LFO. The bigger this value the the time until the LFO starts to oscillate. Эта ручка определяет задержку перед запуском LFO (LFO - НизкоЧастотный осциллятор (генератор)). Чем больше величина, тем больше времени до того как LFO начнёт работать. + LFO- attack: Вступление LFO: + Use this knob for setting attack-time of the current LFO. The bigger this value the longer the LFO needs to increase its amplitude to maximum. Используйте эту ручку для установления времени вступления этого LFO. Чем больше значение, тем дольше LFO нуждается в увеличении своей амплитуды до максимума. + SPD SPD + LFO speed: Скорость LFO: + Use this knob for setting speed of the current LFO. The bigger this value the faster the LFO oscillates and the faster will be your effect. Эта ручка устанавлявает скорость текущего LFO. Чем больше значение, тем быстрее LFO осциллирует и быстрее производится эффект. + Use this knob for setting modulation amount of the current LFO. The bigger this value the more the selected size (e.g. volume or cutoff-frequency) will be influenced by this LFO. Эта ручка устанавливает глубину модуляции для текущего LFO. Чем больше значение, тем в большей степени выбранная характеристика (н-р, громкость или частота среза) будет зависеть от этого LFO. + Click here for a sine-wave. - Генерировать гармонический (синусоидальный) сигнал. + Синусоида. + Click here for a triangle-wave. Сгенерировать треугольный сигнал. + Click here for a saw-wave for current. Сгенерировать зигзагообразный сигнал. + Click here for a square-wave. - Сгенерировать квдратный сигнал (меандр) . + Сгенерировать квадрат. + Click here for a user-defined wave. Afterwards, drag an according sample-file onto the LFO graph. Задать свою форму сигнала. Впоследствии, перетащить соответствующий файл с записью в граф LFO. + + Click here for random wave. + Нажмите сюда для случайной волны. + + + FREQ x 100 ЧАСТОТА x 100 + Click here if the frequency of this LFO should be multiplied by 100. Нажмите, чтобы умножить частоту этого LFO на 100. + multiply LFO-frequency by 100 Умножить частоту LFO на 100 + MODULATE ENV-AMOUNT МОДУЛИР ОГИБАЮЩУЮ + Click here to make the envelope-amount controlled by this LFO. Нажмите сюда, чтобы глубина модуляции огибающей задавалась этим LFO. + control envelope-amount by this LFO Разрешить этому LFO задавать значение огибающей + ms/LFO: мс/LFO: + Hint Подсказка + Drag a sample from somewhere and drop it in this window. Перетащите в это окно какую-нибудь запись. - - Click here for random wave. - Нажмите сюда для случайной волны. - EqControls + Input gain Входная мощность + Output gain Выходная мощность + Low shelf gain - + Низкая ступень усиления + Peak 1 gain - + Пик 1 усиление + Peak 2 gain - + Пик 2 усиление + Peak 3 gain - + Пик 3 усиление + Peak 4 gain - + Пик 4 усиление + High Shelf gain - + Высокая степень усиления + HP res - + ВЧ резон + Low Shelf res - + Низкая ступень резон + Peak 1 BW - + Пик 1 BW + Peak 2 BW - + Пик 2 BW + Peak 3 BW - + Пик 3 BW + Peak 4 BW - + Пик 4 BW + High Shelf res - + Высокая ступень резон + LP res - + НЧ резон + HP freq - + НЧ част + Low Shelf freq - + Низкая степень част + Peak 1 freq - + Пик 1 част + Peak 2 freq - + Пик 2 част + Peak 3 freq - + Пик 3 част + Peak 4 freq - + Пик 4 част + High shelf freq - + Высокая ступень част + LP freq - + НЧ част + HP active - + ВЧ активна + Low shelf active - + Низкая ступень активна + Peak 1 active - + Пик 1 активен + Peak 2 active - + Пик 2 активен + Peak 3 active - + Пик 3 активен + Peak 4 active - + Пик 3 активен + High shelf active - + Высокая степень активна + LP active - + НЧ активна + LP 12 - + НЧ 12 + LP 24 - + НЧ 24 + LP 48 - + НЧ 48 + HP 12 - + ВЧ 12 + HP 24 - + ВЧ 24 + HP 48 - + ВЧ 48 + low pass type - + Тип нижних частот + high pass type - + Тип верхних частот + Analyse IN - + Анализировать ВХОД + Analyse OUT - + Анализировать ВЫХОД EqControlsDialog + HP - + ВЧ + Low Shelf - + Низкая ступень + Peak 1 - + Пик 1 + Peak 2 - + Пик 2 + Peak 3 - + Пик 3 + Peak 4 - + Пик 3 + High Shelf - + Высокая ступень + LP - + НЧ + In Gain Входная мощность + + + Gain Мощность + Out Gain Выходная мощность + Bandwidth: - + Полоса пропускания: + + Octave + Октава + + + Resonance : Резонанс: + Frequency: Частота: + lp grp - + нч grp + hp grp - - - - Octave - Октава + вч grp EqHandle + Reso: - + Резон: + BW: - + BW + + Freq: - + Част: ExportProjectDialog + Export project Экспорт проекта + Output Вывод + File format: Формат файла: + Samplerate: Частота дискретизации: + 44100 Hz 44.1 КГц + 48000 Hz 48 КГц + 88200 Hz 88.2 КГц + 96000 Hz 96 КГц + 192000 Hz 192 КГц - Bitrate: - Частота бит: - - - 64 KBit/s - 64 КБит/с - - - 128 KBit/s - 128 КБит/с - - - 160 KBit/s - 160 КБит/с - - - 192 KBit/s - 192 КБит/с - - - 256 KBit/s - 256 КБит/с - - - 320 KBit/s - 320 КБит/с - - + Depth: Емкость: + 16 Bit Integer 16 Бит целое + + 24 Bit Integer + 24 бита целое + + + 32 Bit Float 32 Бит плавающая + + Stereo mode: + Режим стерео: + + + + Stereo + Стерео + + + + Joint Stereo + Объединённое стерео + + + + Mono + Моно + + + + Bitrate: + Частота бит: + + + + 64 KBit/s + 64 КБит/с + + + + 128 KBit/s + 128 КБит/с + + + + 160 KBit/s + 160 КБит/с + + + + 192 KBit/s + 192 КБит/с + + + + 256 KBit/s + 256 КБит/с + + + + 320 KBit/s + 320 КБит/с + + + + Use variable bitrate + Использовать плавающую глубину битности + + + Quality settings Настройки качества + Interpolation: Интерполяция: + Zero Order Hold Нулевая задержка + Sinc Fastest Синхр. Быстрая + Sinc Medium (recommended) Синхр. Средняя (рекомендовано) + Sinc Best (very slow!) Синхр. лучшая (очень медленно!) + Oversampling (use with care!): Передискретизация (использовать осторожно!): + 1x (None) 1х (Нет) + 2x + 4x + 8x - Start - Начать - - - Cancel - Отменить - - + Export as loop (remove end silence) Экспортировать как петлю (убрать тишину в конце) + Export between loop markers Экспорт между метками петли + + Start + Начать + + + + Cancel + Отменить + + + Could not open file Не могу открыть файл - Export project to %1 - Экспорт проекта в %1 - - - Error - Ошибка - - - Error while determining file-encoder device. Please try to choose a different output format. - Ошибка при определении кодека файла. Попробуйте выбрать другой формат вывода. - - - Rendering: %1% - Обработка: %1% - - + Could not open file %1 for writing. Please make sure you have write permission to the file and the directory containing the file and try again! Невозможно открыть файл %1 для записи. Пожалуйста, убедитесь, что у вас есть разрешение на запись в файл и содержащую его директорию, и попробуйте снова. - 24 Bit Integer - 24 бита целое + + Export project to %1 + Экспорт проекта в %1 - Use variable bitrate - И + + Error + Ошибка - Stereo mode: - + + Error while determining file-encoder device. Please try to choose a different output format. + Ошибка при определении кодека файла. Попробуйте выбрать другой формат вывода. - Stereo - - - - Joint Stereo - - - - Mono - + + Rendering: %1% + Обработка: %1% Compression level: @@ -2155,6 +2675,8 @@ Please make sure you have write permission to the file and the directory contain Fader + + Please enter a new value between %1 and %2: Введите новое значение от %1 до %2: @@ -2162,6 +2684,7 @@ Please make sure you have write permission to the file and the directory contain FileBrowser + Browser Обозреватель файлов @@ -2177,123 +2700,151 @@ Please make sure you have write permission to the file and the directory contain FileBrowserTreeWidget + Send to active instrument-track Послать на активную инструментальную-дорожку - Open in new instrument-track/B+B Editor - Открыть в новой инструментальной дорожке/Б+Б редакторе - - - Loading sample - Загрузка записи - - - Please wait, loading sample for preview... - Пж. ждите, запись загружается для просмотра... - - - --- Factory files --- - --- Заводские файлы --- - - + Open in new instrument-track/Song Editor Отркрыть в новой инструментальной дорожке/редакторе песни + + Open in new instrument-track/B+B Editor + Открыть в новой инструментальной дорожке/Б+Б редакторе + + + + Loading sample + Загрузка записи + + + + Please wait, loading sample for preview... + Пж. ждите, запись загружается для просмотра... + + + Error Ошибка + does not appear to be a valid Не похоже на правильное + file файл + + + --- Factory files --- + --- Заводские файлы --- + FlangerControls + Delay Samples Задержка сэмплов + Lfo Frequency Частота LFO + Seconds Секунды + Regen + Noise Шум + Invert - + Инвертировать FlangerControlsDialog - Delay Time: - Время задержки: - - - Feedback Amount: - Объём возврата: - - - White Noise Amount: - Объём белого шума: - - + DELAY Задержка + + Delay Time: + Время задержки: + + + RATE ЧАСТ + + Period: + Период: + + + AMNT ГЛУБ + Amount: - + Величина: + FDBK + + Feedback Amount: + Объём возврата: + + + NOISE Шум - Invert - + + White Noise Amount: + Объём белого шума: - Period: - + + Invert + Инвертировать FxLine + Channel send amount Величина отправки канала + The FX channel receives input from one or more instrument tracks. It in turn can be routed to multiple other FX channels. LMMS automatically takes care of preventing infinite loops for you and doesn't allow making a connection that would result in an infinite loop. @@ -2308,22 +2859,27 @@ You can remove and move FX channels in the context menu, which is accessed by ri + Move &left Двигать влево &L + Move &right Двигать вправо &r + Rename &channel Переименовать канал &c + R&emove channel Удалить канал &e + Remove &unused channels Удалить неиспользуемые каналы &u @@ -2331,22 +2887,29 @@ You can remove and move FX channels in the context menu, which is accessed by ri FxMixer + Master Главный + + + FX %1 Эффект %1 + Volume Громкость + Mute Тихо + Solo Соло @@ -2354,26 +2917,32 @@ You can remove and move FX channels in the context menu, which is accessed by ri FxMixerView + FX-Mixer Микшер Эффектов + FX Fader %1 + Mute Тихо + Mute this FX channel Заглушить этот канал ЭФ + Solo Соло + Solo FX channel Соло канал ЭФ @@ -2381,6 +2950,8 @@ You can remove and move FX channels in the context menu, which is accessed by ri FxRoute + + Amount to send from channel %1 to channel %2 Величина отправки с канала %1 на канал %2 @@ -2388,14 +2959,17 @@ You can remove and move FX channels in the context menu, which is accessed by ri GigInstrument + Bank Банк + Patch Патч + Gain Мощность @@ -2403,46 +2977,58 @@ You can remove and move FX channels in the context menu, which is accessed by ri GigInstrumentView + Open other GIG file Открыть другой GIG файл + Click here to open another GIG file Кликните сюда, чтобы открыть другой GIG файл + Choose the patch Выбрать патч + Click here to change which patch of the GIG file to use Нажмите здесь для смены используемого патча GIG файла + + Change which instrument of the GIG file is being played Изменить инструмент, который воспроизводит GIG файл + Which GIG file is currently being used Какой GIG файл сейчас используется + Which patch of the GIG file is currently being used Какой патч GIG файла сейчас используется + Gain - Мощность + УСИЛ + Factor to multiply samples by Фактор умножения сэмплов + Open GIG file Открыть GIG файл + GIG Files (*.gig) GIG Файлы (*.gig) @@ -2450,42 +3036,52 @@ You can remove and move FX channels in the context menu, which is accessed by ri GuiApplication + Working directory Рабочий каталог + The LMMS working directory %1 does not exist. Create it now? You can change the directory later via Edit -> Settings. Рабочий каталог LMMS (%1) не существует. Создать его? Позже вы сможете сменить его через Правка -> Параметры. + Preparing UI Подготовка UI + Preparing song editor Подготовка редактора песни + Preparing mixer Подготовка микшера + Preparing controller rack Подготовка стойки управления + Preparing project notes Подготовка заметок проекта + Preparing beat/bassline editor Подготовка Ритм+Бас редактора + Preparing piano roll Подготовка редактора нот + Preparing automation editor Подготовка редактора автоматизации @@ -2493,650 +3089,814 @@ You can remove and move FX channels in the context menu, which is accessed by ri InstrumentFunctionArpeggio + Arpeggio Арпеджио + Arpeggio type Тип арпеджио + Arpeggio range Диапазон арпеджио - Arpeggio time - Период арпеджио - - - Arpeggio gate - Шлюз арпеджио - - - Arpeggio direction - Направление арпеджио - - - Arpeggio mode - Режим арпеджио - - - Up - Вверх - - - Down - Вниз - - - Up and down - Вверх и вниз - - - Random - Случайно - - - Free - Свободно - - - Sort - Упорядочить - - - Sync - Синхронизировать - - - Down and up - Вниз и вверх - - - Skip rate + + Cycle steps + + Skip rate + Частота пропуска + + + Miss rate - Cycle steps - + + Arpeggio time + Период арпеджио + + + + Arpeggio gate + Шлюз арпеджио + + + + Arpeggio direction + Направление арпеджио + + + + Arpeggio mode + Режим арпеджио + + + + Up + Вверх + + + + Down + Вниз + + + + Up and down + Вверх и вниз + + + + Down and up + Вниз и вверх + + + + Random + Случайно + + + + Free + Свободно + + + + Sort + Упорядочить + + + + Sync + Синхронизировать InstrumentFunctionArpeggioView + ARPEGGIO ARPEGGIO + An arpeggio is a method playing (especially plucked) instruments, which makes the music much livelier. The strings of such instruments (e.g. harps) are plucked like chords. The only difference is that this is done in a sequential order, so the notes are not played at the same time. Typical arpeggios are major or minor triads, but there are a lot of other possible chords, you can select. Арпеджио — разновидность исполнения аккордов на фортепиано и струнных инструментах, которая оживляет звучание. Струнф таких инструментов играются перебором по аккордам, как на арфе, когда звуки аккорда следуют один за другим. Типичные арпеджио - мажорные и минорные триады, среди которых можно выбрать и другие. + RANGE RANGE + Arpeggio range: Диапазон арпеджио: + octave(s) Октав[а/ы] + Use this knob for setting the arpeggio range in octaves. The selected arpeggio will be played within specified number of octaves. Используйте эту ручку, чтобы установить диапазон арпеджио (в октавах). Выбранный тип арпеджио будет охватывать указанное количество октав. - TIME - TIME - - - Arpeggio time: - Период арпеджио: - - - ms - мс - - - Use this knob for setting the arpeggio time in milliseconds. The arpeggio time specifies how long each arpeggio-tone should be played. - Регулировка периода арпеджио - время (в миллисекундах), которое должен звучать каждый тон арпеджио. - - - GATE - GATE - - - Arpeggio gate: - Шлюз арпеджио: - - - % - % - - - Use this knob for setting the arpeggio gate. The arpeggio gate specifies the percent of a whole arpeggio-tone that should be played. With this you can make cool staccato arpeggios. - Регулировка шлюза арпеджио, показывает процентную долю каждого тона арпеджио, которая будет воспроизведена. Простой способ создавать стаккато-арпеджио. - - - Chord: - Аккорд: - - - Direction: - Направление: - - - Mode: - Режим: - - - SKIP - - - - Skip rate: - - - - The skip function will make the arpeggiator pause one step randomly. From its start in full counter clockwise position and no effect it will gradually progress to full amnesia at maximum setting. - - - - MISS - - - - Miss rate: - - - - The miss function will make the arpeggiator miss the intended note. - - - + CYCLE - + ЦИКЛ + Cycle notes: + note(s) нота(ы) + Jumps over n steps in the arpeggio and cycles around if we're over the note range. If the total note range is evenly divisible by the number of steps jumped over you will get stuck in a shorter arpeggio or even on one note. + + + SKIP + ПРОПУСК + + + + Skip rate: + Частота пропуска: + + + + + + % + % + + + + The skip function will make the arpeggiator pause one step randomly. From its start in full counter clockwise position and no effect it will gradually progress to full amnesia at maximum setting. + + + + + MISS + ПРОПУСК + + + + Miss rate: + + + + + The miss function will make the arpeggiator miss the intended note. + + + + + TIME + TIME + + + + Arpeggio time: + Период арпеджио: + + + + ms + мс + + + + Use this knob for setting the arpeggio time in milliseconds. The arpeggio time specifies how long each arpeggio-tone should be played. + Регулировка периода арпеджио - время (в миллисекундах), которое должен звучать каждый тон арпеджио. + + + + GATE + GATE + + + + Arpeggio gate: + Шлюз арпеджио: + + + + Use this knob for setting the arpeggio gate. The arpeggio gate specifies the percent of a whole arpeggio-tone that should be played. With this you can make cool staccato arpeggios. + Регулировка шлюза арпеджио, показывает процентную долю каждого тона арпеджио, которая будет воспроизведена. Простой способ создавать стаккато-арпеджио. + + + + Chord: + Аккорд: + + + + Direction: + Направление: + + + + Mode: + Режим: + InstrumentFunctionNoteStacking + octave Октава + + Major Мажорный + Majb5 - + Majb5 + minor минорный + minb5 - + minb5 + sus2 - + sus2 + sus4 - + sus4 + aug - + aug + augsus4 - + augsus4 + tri - + tri + 6 - + 6 + 6sus4 - + 6sus4 + 6add9 - + 6add9 + m6 - + m6 + m6add9 - + m6add9 + 7 - + 7 + 7sus4 - + 7sus4 + 7#5 - + 7#5 + 7b5 - + 7b5 + 7#9 - + 7#9 + 7b9 - + 7b9 + 7#5#9 - + 7#5#9 + 7#5b9 - + 7#5b9 + 7b5b9 - + 7b5b9 + 7add11 - + 7add11 + 7add13 - + 7add13 + 7#11 - + 7#11 + Maj7 - + Maj7 + Maj7b5 - + Maj7b5 + Maj7#5 - + Maj7#5 + Maj7#11 - + Maj7#11 + Maj7add13 - + Maj7add13 + m7 - + m7 + m7b5 - + m7b5 + m7b9 - + m7b9 + m7add11 - + m7add11 + m7add13 - + m7add13 + m-Maj7 - + m-Maj7 + m-Maj7add11 - + m-Maj7add11 + m-Maj7add13 - + m-Maj7add13 + 9 - + 9 + 9sus4 - + 9sus4 + add9 - + add9 + 9#5 - + 9#5 + 9b5 - + 9b5 + 9#11 - + 9#11 + 9b13 - + 9b13 + Maj9 - + Maj9 + Maj9sus4 - + Maj9sus4 + Maj9#5 - + Maj9#5 + Maj9#11 - + Maj9#11 + m9 - + m9 + madd9 - + madd9 + m9b5 - + m9b5 + m9-Maj7 - + m9-Maj7 + 11 - + 11 + 11b9 - + 11b9 + Maj11 - + Maj11 + m11 - + m11 + m-Maj11 - + m-Maj11 + 13 - + 13 + 13#9 - + 13#9 + 13b9 - + 13b9 + 13b5b9 - + 13b5b9 + Maj13 - + Maj13 + m13 - + m13 + m-Maj13 - + m-Maj13 + Harmonic minor - + Гармонический минор + Melodic minor - + Мелодический минор + Whole tone - + Целый тон + Diminished - + Пониженный + Major pentatonic - + Мажорная пентатоника + Minor pentatonic - + Минорная пентатоника + Jap in sen + Major bebop + Dominant bebop + Blues - + Blues + Arabic - + Арабский + Enigmatic + Neopolitan - + Неополитанский + Neopolitan minor - + Неополитанский минор + Hungarian minor + Dorian - + Дорийский - Phrygolydian - + + Phrygian + Фригийский + Lydian - + Лидийский + Mixolydian - + Миксолидийский + Aeolian - + Эолийский + Locrian - Chords - Аккорды - - - Chord type - Тип аккорда - - - Chord range - Диапазон аккорда - - + Minor + Chromatic - + Хроматический + Half-Whole Diminished + 5 - + 5 + Phrygian dominant + Persian + + + Chords + Аккорды + + + + Chord type + Тип аккорда + + + + Chord range + Диапазон аккорда + InstrumentFunctionNoteStackingView - RANGE - ДИАП - - - Chord range: - Диапазон аккорда: - - - octave(s) - Октав[а/ы] - - - Use this knob for setting the chord range in octaves. The selected chord will be played within specified number of octaves. - Эта ручка изменяет диапазон аккорда, который будет содержать указанное число октав. - - + STACKING СТЫКОВКА + Chord: Аккорд: + + + RANGE + ДИАП + + + + Chord range: + Диапазон аккорда: + + + + octave(s) + Октав[а/ы] + + + + Use this knob for setting the chord range in octaves. The selected chord will be played within specified number of octaves. + Эта ручка изменяет диапазон аккорда, который будет содержать указанное число октав. + InstrumentMidiIOView + ENABLE MIDI INPUT ВКЛ MIDI ВВОД + + CHANNEL CHANNEL + + VELOCITY VELOCITY + ENABLE MIDI OUTPUT ВКЛ MIDI ВЫВОД + PROGRAM PROGRAM - MIDI devices to receive MIDI events from - MiDi устройства-источники событий - - - MIDI devices to send MIDI events to - MiDi устройства для отправки событий на них - - + NOTE NOTE + + MIDI devices to receive MIDI events from + MiDi устройства-источники событий + + + + MIDI devices to send MIDI events to + MiDi устройства для отправки событий на них + + + CUSTOM BASE VELOCITY ПРОИЗВОЛЬНАЯ БАЗОВАЯ СКОРОСТЬ + Specify the velocity normalization base for MIDI-based instruments at 100% note velocity Определяет базовую скорость нормализации для MiDi инструментов при громкости ноты 100% + BASE VELOCITY БАЗОВАЯ СКОРОСТЬ @@ -3144,10 +3904,12 @@ You can remove and move FX channels in the context menu, which is accessed by ri InstrumentMiscView + MASTER PITCH - + Мастер-высота + Enables the use of Master Pitch Включает использование основной тональности @@ -3155,178 +3917,222 @@ You can remove and move FX channels in the context menu, which is accessed by ri InstrumentSoundShaping + VOLUME VOLUME + Volume Громкость + CUTOFF CUTOFF + + Cutoff frequency Срез частоты + RESO RESO + Resonance Резонанс + Envelopes/LFOs Огибание/LFO + Filter type Тип фильтра + Q/Resonance + LowPass Низ.ЧФ + HiPass Выс.ЧФ + BandPass csg Сред.ЧФ csg + BandPass czpg Сред.ЧФ czpg + Notch Полосно-заграждающий + Allpass Все проходят + Moog Муг + 2x LowPass 2х Низ.ЧФ + RC LowPass 12dB RC Низ.ЧФ 12дБ + RC BandPass 12dB RC Сред.ЧФ 12 дБ + RC HighPass 12dB RC Выс.ЧФ 12дБ + RC LowPass 24dB RC Низ.ЧФ 24дБ + RC BandPass 24dB RC Сред.ЧФ 24дБ + RC HighPass 24dB RC Выс.ЧФ 24дБ + Vocal Formant Filter Фильтр Вокальной форманты + 2x Moog 2x Муг + SV LowPass SV Низ.ЧФ + SV BandPass SV Сред.ЧФ + SV HighPass SV Выс.ЧФ + SV Notch + Fast Formant + Tripole - + Триполи InstrumentSoundShapingView + TARGET ЦЕЛЬ + These tabs contain envelopes. They're very important for modifying a sound, in that they are almost always necessary for substractive synthesis. For example if you have a volume envelope, you can set when the sound should have a specific volume. If you want to create some soft strings then your sound has to fade in and out very softly. This can be done by setting large attack and release times. It's the same for other envelope targets like panning, cutoff frequency for the used filter and so on. Just monkey around with it! You can really make cool sounds out of a saw-wave with just some envelopes...! Эта вкладка позволяет вам настроить огибающие. Они очень важны для настройки звучания. Например, с помощью огибающей громкости вы можете задать зависимость громкости звучания от времени. Если вам понадобится эмулировать мягкие струнные, просто задайте больше времени нарастания и исчезновения звука. С помощью обгибающих и низкочастотного осцилятора (LFO) вы в несколько щелчков мыши сможете создать просто невероятные звуки! + FILTER ФИЛЬТР + Here you can select the built-in filter you want to use for this instrument-track. Filters are very important for changing the characteristics of a sound. Здесь вы можете выбрать фильтр для дорожки этого инструмента. Фильтры могут довольно сильно менять звучание. - Hz - Гц - - - Use this knob for setting the cutoff frequency for the selected filter. The cutoff frequency specifies the frequency for cutting the signal by a filter. For example a lowpass-filter cuts all frequencies above the cutoff frequency. A highpass-filter cuts all frequencies below cutoff frequency, and so on... - Эта ручка устанавливает частоту среза для выбранного фильтра. К примеру, ФНЧ будет срезать сигнал на частотах выше частоты среза, полосно-пропускающий фильтр будет хорошо пропускать сигнал только на заданной частоте и так далее... - - - RESO - RESO - - - Resonance: - Резонанс: - - - Use this knob for setting Q/Resonance for the selected filter. Q/Resonance tells the filter how much it should amplify frequencies near Cutoff-frequency. - Эта ручка задаёт количество резонанса для фильтра, этим определяется насколько нужно усилить ближайшие к отрезанным частоты. - - + FREQ ЧАСТ + cutoff frequency: Срез частот: + + Hz + Гц + + + + Use this knob for setting the cutoff frequency for the selected filter. The cutoff frequency specifies the frequency for cutting the signal by a filter. For example a lowpass-filter cuts all frequencies above the cutoff frequency. A highpass-filter cuts all frequencies below cutoff frequency, and so on... + Эта ручка устанавливает частоту среза для выбранного фильтра. К примеру, ФНЧ будет срезать сигнал на частотах выше частоты среза, полосно-пропускающий фильтр будет хорошо пропускать сигнал только на заданной частоте и так далее... + + + + RESO + RESO + + + + Resonance: + Усиление: + + + + Use this knob for setting Q/Resonance for the selected filter. Q/Resonance tells the filter how much it should amplify frequencies near Cutoff-frequency. + Эта ручка задаёт количество резонанса для фильтра, этим определяется насколько нужно усилить ближайшие к отрезанным частоты. + + + Envelopes, LFOs and filters are not supported by the current instrument. Огибающие, LFO и фильтры не поддерживаются этим инструментом. @@ -3334,85 +4140,107 @@ You can remove and move FX channels in the context menu, which is accessed by ri InstrumentTrack - unnamed_track - безымянная_дорожка - - - Volume - Громкость - - - Panning - Стерео - - - Pitch - Тональность - - - FX channel - Канал ЭФ - - - Default preset - Основная предустановка - - + With this knob you can set the volume of the opened channel. Регулировка громкости текущего канала. + + + unnamed_track + безымянная_дорожка + + + Base note Опорная нота + + Volume + Громкость + + + + Panning + Стерео + + + + Pitch + Тональность + + + Pitch range Диапазон тональности + + FX channel + Канал ЭФ + + + Master Pitch - + Основная тональность + + + + + Default preset + Основная предустановка InstrumentTrackView + Volume Громкость + Volume: Громкость: + VOL ГРОМ + Panning Баланс + Panning: Баланс: + PAN БАЛ + MIDI MIDI + Input Вход + Output Выход + FX %1: %2 ЭФ %1: %2 @@ -3420,136 +4248,168 @@ You can remove and move FX channels in the context menu, which is accessed by ri InstrumentTrackWindow + GENERAL SETTINGS ОСНОВНЫЕ НАСТРОЙКИ - Instrument volume - Громкость инструмента - - - Volume: - Громкость: - - - VOL - ГРОМ - - - Panning - Баланс - - - Panning: - Стереобаланс: - - - PAN - БАЛ - - - Pitch - Тональность - - - Pitch: - Тональность: - - - cents - процентов - - - PITCH - ТОН - - - FX channel - Канал ЭФ - - - FX - ЭФ - - - Save preset - Сохранить предустановку - - - XML preset file (*.xpf) - XML файл настроек (*.xpf) - - - Pitch range (semitones) - Диапазон тональности (полутона) - - - RANGE - ДИАП - - - Save current instrument track settings in a preset file - Сохранить текущую инструментаьную дорожку в файл предустановок - - - Click here, if you want to save current instrument track settings in a preset file. Later you can load this preset by double-clicking it in the preset-browser. - Нажать здесь, чтобы сохранить настройки текущей инстр. дорожки в файл предустановок. Позже можно загрузить эту предустановку двойным кликом в браузере предустановок. - - + Use these controls to view and edit the next/previous track in the song editor. Используйте эти регуляторы, чтобы видеть и редактировать дорожку в редакторе песни. + + Instrument volume + Громкость инструмента + + + + Volume: + Громкость: + + + + VOL + ГРОМ + + + + Panning + Баланс + + + + Panning: + Стереобаланс: + + + + PAN + БАЛ + + + + Pitch + Тональность + + + + Pitch: + Тональность: + + + + cents + процентов + + + + PITCH + ТОН + + + + Pitch range (semitones) + Диапазон тональности (полутона) + + + + RANGE + ДИАП + + + + FX channel + Канал ЭФ + + + + FX + ЭФ + + + + Save current instrument track settings in a preset file + Сохранить текущую инструментаьную дорожку в файл предустановок + + + + Click here, if you want to save current instrument track settings in a preset file. Later you can load this preset by double-clicking it in the preset-browser. + Нажать здесь, чтобы сохранить настройки текущей инстр. дорожки в файл предустановок. Позже можно загрузить эту предустановку двойным кликом в браузере предустановок. + + + SAVE Сохранить + Envelope, filter & LFO + Chord stacking & arpeggio + Effects - + Эффекты + MIDI settings Параметры MIDI + Miscellaneous - + Разное + + Save preset + Сохранить предустановку + + + + XML preset file (*.xpf) + XML файл настроек (*.xpf) + + + Plugin - + Модуль Knob + Set linear Установить линейно + Set logarithmic Установить логарифмически - Please enter a new value between %1 and %2: - Введите новое значение от %1 до %2: - - + Please enter a new value between -96.0 dBFS and 6.0 dBFS: Введите новое значение от –96,0 дБВ до 6,0 дБВ: + + + Please enter a new value between %1 and %2: + Введите новое значение от %1 до %2: + LadspaControl + Link channels Связать каналы @@ -3557,10 +4417,12 @@ You can remove and move FX channels in the context menu, which is accessed by ri LadspaControlDialog + Link Channels Связать каналы + Channel Канал @@ -3568,14 +4430,17 @@ You can remove and move FX channels in the context menu, which is accessed by ri LadspaControlView + Link channels Связать каналы + Value: Значение: + Sorry, no help available. Извините, справки нет. @@ -3583,6 +4448,7 @@ You can remove and move FX channels in the context menu, which is accessed by ri LadspaEffect + Unknown LADSPA plugin %1 requested. Запрошен неизвестный модуль LADSPA «%1». @@ -3590,6 +4456,7 @@ You can remove and move FX channels in the context menu, which is accessed by ri LcdSpinBox + Please enter a new value between %1 and %2: Введите новое значение от %1 до %2: @@ -3597,18 +4464,26 @@ You can remove and move FX channels in the context menu, which is accessed by ri LeftRightNav + + + Previous Предыдущий + + + Next Следующий + Previous (%1) Предыдущий (%1) + Next (%1) Следующий (%1) @@ -3616,30 +4491,37 @@ You can remove and move FX channels in the context menu, which is accessed by ri LfoController + LFO Controller Контроллер LFO + Base value Основное значение + Oscillator speed Скорость волны + Oscillator amount Размер волны + Oscillator phase Фаза волны + Oscillator waveform Форма волны + Frequency Multiplier Множитель частоты @@ -3647,115 +4529,142 @@ You can remove and move FX channels in the context menu, which is accessed by ri LfoControllerDialog + LFO LFO + LFO Controller Контроллер LFO + BASE БАЗА + Base amount: - Кол-во базы: + Базовое значение: + todo доделать + SPD СКОР + LFO-speed: Скорость LFO: + Use this knob for setting speed of the LFO. The bigger this value the faster the LFO oscillates and the faster the effect. Эта ручка устанавлявает скорость LFO. Чем больше значение, тем больше частота осциллятора. + + AMNT + ГЛУБ + + + Modulation amount: Количество модуляции: + Use this knob for setting modulation amount of the LFO. The bigger this value, the more the connected control (e.g. volume or cutoff-frequency) will be influenced by the LFO. Эта ручка устанавливает глубину модуляции для LFO. Чем больше значение, тем в большей степени выбранная характеристика (н-р, громкость или частота среза) будет зависеть от ГНЧ(LFO). + PHS ФАЗА + Phase offset: Сдвиг фазы: + degrees градусы + With this knob you can set the phase offset of the LFO. That means you can move the point within an oscillation where the oscillator begins to oscillate. For example if you have a sine-wave and have a phase-offset of 180 degrees the wave will first go down. It's the same with a square-wave. Эта ручка устанавливает начальную фазу НизкоЧастотного Осциллятора (LFO), т. е. точку, с которой осциллятор начинает вырабатывать сигнал. Например, если вы задали синусоидальную форму сигнала и начальную фазу 180º, волна сначала пойдёт вниз, а не вверх, так же как и для квадратной волны. + Click here for a sine-wave. Синусоида. + Click here for a triangle-wave. - Треугольник. + Сгенерировать треугольный сигнал. + Click here for a saw-wave. - Зигзаг. + Сгенерировать зигзаг. + Click here for a square-wave. - Квадрат. + Сгенерировать квадрат. + + Click here for a moog saw-wave. + Нажать здесь для зигзагообразной муг волны. + + + Click here for an exponential wave. - Экспонента. + Генерировать экспоненциальный сигнал. + Click here for white-noise. - Белый шум. + Сгенерировать белый шум. + Click here for a user-defined shape. Double click to pick a file. Нажмите здесь для определения своей формы. Двойное нажатие для выбора файла. - - Click here for a moog saw-wave. - Нажать здесь для зигзагообразной муг волны. - - - AMNT - ГЛУБ - LmmsCore + Generating wavetables Генерация волн + Initializing data structures Инициализация структуры данных + Opening audio and midi devices Открываем аудио и миди устройства + Launching mixer threads Запускаем потоки микшера @@ -3763,399 +4672,504 @@ Double click to pick a file. MainWindow + Settings + Параметры + + Configuration file + Файл настроек + + + + Error while parsing configuration file at line %1:%2: %3 + Ошибка во время обработки файла настроек в строке %1:%2: %3 + + + + Could not open file + Не могу открыть файл + + + + Could not open file %1 for writing. +Please make sure you have write permission to the file and the directory containing the file and try again! + Невозможно открыть файл %1 для записи. Пожалуйста, убедитесь, что у вас есть разрешение на запись в файл и содержащую его директорию, и попробуйте снова. + + + + Project recovery + Восстановление проекта + + + + There is a recovery file present. It looks like the last session did not end properly or another instance of LMMS is already running. Do you want to recover the project of this session? + Остался файл для восстановления. Похоже последняя сессия не была нормально завершена или запущен ещё один процесс LMMS. +Хотите восстановить проект из этой сессии? + + + + + + Recover + Восстановить + + + + Recover the file. Please don't run multiple instances of LMMS when you do this. + Восстановить файл. Пожалуйства, не запускайте несколько процессов ЛММС во время этого. + + + + + + Discard + Отказать + + + + Launch a default session and delete the restored files. This is not reversible. + Запустить обычную сессию и удалить восстановленные файлы. Это безвозвратно. + + + + Version %1 + Версия %1 + + + + Preparing plugin browser + Подготовка обзора плагинов + + + + Preparing file browsers + Подготовка обзора файлов + + + + My Projects + Мои проекты + + + + My Samples + Мои сэмплы + + + + My Presets + Мои предустановки + + + + My Home + Моя домашняя папка + + + + Root directory + Корневая директория + + + + Volumes + Громкость 1 оциллятора + + + + My Computer + Мой компьютер + + + + Loading background artwork + Загружаем фоновый рисунок + + + + &File + &F Файл + + + &New &N Новый + + New from template + Новый на основе шаблона + + + &Open... &Открыть... + + &Recently Opened Projects + &R Недавние проекты + + + &Save &S Сохранить + Save &As... &A Сохранить как... + + Save as New &Version + &V Сохранить как новую версию + + + + Save as default template + Сохранить как обычный шаблон + + + Import... Импорт... + E&xport... &X Экспорт... + + E&xport Tracks... + &x Экспорт дорожек... + + + + Export &MIDI... + Экспорт &MIDI... + + + &Quit &Q Выйти + &Edit &E Правка + + Undo + Откатить действие + + + + Redo + Возврат действия + + + Settings Параметры + + &View + &Просмотр + + + &Tools &T Сервис + &Help &H Справка + + Online Help + Помощь онлайн + + + Help Справка - What's this? + + What's This? Что это? + About О программе + Create new project Создать новый проект + Create new project from template Создать новый проект по шаблону + Open existing project Открыть существующий проект + Recently opened projects Недавние проекты + Save current project Сохранить текущий проект + Export current project Экспорт проекта - Song Editor + + What's this? + Что это? + + + + Toggle metronome + Включить метроном + + + + Show/hide Song-Editor Показать/скрыть музыкальный редактор + By pressing this button, you can show or hide the Song-Editor. With the help of the Song-Editor you can edit song-playlist and specify when which track should be played. You can also insert and move samples (e.g. rap samples) directly into the playlist. Сим запускается или скрывается музыкальный редактор. С его помощью вы можете редактировать композицию и задавать время воспроизведения каждой дорожки. Также вы можете вставлять и передвигать записи прямо в списке воспроизведения. - Beat+Bassline Editor - Показать/скрыть ритм-бас редактор + + Show/hide Beat+Bassline Editor + Показать/скрыть Ритм+Бас редактор + By pressing this button, you can show or hide the Beat+Bassline Editor. The Beat+Bassline Editor is needed for creating beats, and for opening, adding, and removing channels, and for cutting, copying and pasting beat and bassline-patterns, and for other things like that. Сим запускается ритм-бас редактор. Он необходим для установки ритма, открытия, добавления и удаления каналов, а также вырезания, копирования и вставки ритм-бас шаблонов, мелодий и т. п. - Piano Roll - Показать/скрыть нотный редактор + + Show/hide Piano-Roll + Показать/Скрыть Редактор Нот + Click here to show or hide the Piano-Roll. With the help of the Piano-Roll you can edit melodies in an easy way. Запуск редатора нот. С его помощью вы можете легко редактировать мелодии. - Automation Editor + + Show/hide Automation Editor Показать/скрыть редактор автоматизации + Click here to show or hide the Automation Editor. With the help of the Automation Editor you can edit dynamic values in an easy way. Показать/скрыть окно редактора автоматизации. С его помощью вы можете легко редактироватьдинамику выбранных величин. - FX Mixer + + Show/hide FX Mixer Показать/скрыть микшер ЭФ + Click here to show or hide the FX Mixer. The FX Mixer is a very powerful tool for managing effects for your song. You can insert effects into different effect-channels. Скрыть/показать микшер ЭФфектов. Он является мощным инструментом для управления эффектами. Вы можете вставлять эффекты в различные каналы. - Project Notes - Показать/скрыть заметки к проекту + + Show/hide project notes + Показать/скрыть заметки проекта + Click here to show or hide the project notes window. In this window you can put down your project notes. Эта кнопка показывает/прячет окно с заметками. В этом окне вы можете помещать любые комментарии к своей композиции. - Controller Rack + + Show/hide controller rack Показать/скрыть управление контроллерами + Untitled Неназванный + + Recover session. Please save your work! + Восстановление сессии. Пожалуйста, сохраните свою работу! + + + LMMS %1 LMMS %1 + + Recovered project not saved + Восстановленный проект не сохранён. + + + + This project was recovered from the previous session. It is currently unsaved and will be lost if you don't save it. Do you want to save it now? + Проект был восстановлен из предыдущей сессии. Сейчас он не сохранён и будет потерян, если его не сохранить. +Хотите сохранить его сейчас? + + + Project not saved Проект не сохранён + The current project was modified since last saving. Do you want to save it now? Проект был изменён. Сохранить его сейчас? + + Open Project + Открыть проект + + + + LMMS (*.mmp *.mmpz) + LMMS (*.mmp *.mmpz) + + + + Save Project + Сохранить проект + + + + LMMS Project + ЛММС Проект + + + + LMMS Project Template + Шаблон ЛММС Проекта + + + + Save project template + + + + + Overwrite default template? + Перезаписать обычный шаблон? + + + + This will overwrite your current default template. + Это перезапишет текущий обычный шаблон. + + + Help not available Справка недоступна + Currently there's no help available in LMMS. Please visit http://lmms.sf.net/wiki for documentation on LMMS. Пока что справка для LMMS не написана. Вероятно, Вы сможете найти нужные материалы на http://lmms.sf.net/wiki . - LMMS (*.mmp *.mmpz) - LMMS (*.mmp *.mmpz) - - - Version %1 - Версия %1 - - - Configuration file - Файл настроек - - - Error while parsing configuration file at line %1:%2: %3 - Ошибка во время обработки файла настроек в строке %1:%2: %3 - - - Volumes - Громкость 1 оциллятора - - - Undo - Откатить действие - - - Redo - Возврат действия - - - My Projects - Мои проекты - - - My Samples - Мои сэмплы - - - My Presets - Мои предустановки - - - My Home - Моя домашняя папка - - - My Computer - Мой компьютер - - - &File - &F Файл - - - &Recently Opened Projects - &R Недавние проекты - - - Save as New &Version - &V Сохранить как новую версию - - - E&xport Tracks... - &x Экспорт дорожек... - - - Online Help - Помощь онлайн - - - What's This? - Что это? - - - Open Project - Открыть проект - - - Save Project - Сохранить проект - - - Project recovery - Восстановление проекта - - - There is a recovery file present. It looks like the last session did not end properly or another instance of LMMS is already running. Do you want to recover the project of this session? - Остался файл для восстановления. Похоже последняя сессия не была нормально завершена или запущен ещё один процесс LMMS. -Хотите восстановить проект из этой сессии? - - - Recover - Восстановить - - - Recover the file. Please don't run multiple instances of LMMS when you do this. - Восстановить файл. Пожалуйства, не запускайте несколько процессов ЛММС во время этого. - - - Discard - Отказать - - - Launch a default session and delete the restored files. This is not reversible. - Запустить обычную сессию и удалить восстановленные файлы. Это безвозвратно. - - - Preparing plugin browser - Подготовка обзора плагинов - - - Preparing file browsers - Подготовка обзора файлов - - - Root directory - Корневая директория - - - Loading background artwork - Загружаем фоновый рисунок - - - New from template - - - - Save as default template - Сохранить как обычный шаблон - - - &View - - - - Toggle metronome - Включить метроном - - - Show/hide Song-Editor + + Song Editor Показать/скрыть музыкальный редактор - Show/hide Beat+Bassline Editor - Показать/скрыть Ритм+Бас редактор + + Beat+Bassline Editor + Показать/скрыть ритм-бас редактор - Show/hide Piano-Roll - Показать/Скрыть Редактор Нот + + Piano Roll + Показать/скрыть нотный редактор - Show/hide Automation Editor + + Automation Editor Показать/скрыть редактор автоматизации - Show/hide FX Mixer + + FX Mixer Показать/скрыть микшер ЭФ - Show/hide project notes - Показать/скрыть заметки проекта + + Project Notes + Показать/скрыть заметки к проекту - Show/hide controller rack + + Controller Rack Показать/скрыть управление контроллерами - Recover session. Please save your work! - Восстановление сессии. Пожалуйста, сохраните свою работу! - - - Recovered project not saved - Восстановленный проект не сохранён. - - - This project was recovered from the previous session. It is currently unsaved and will be lost if you don't save it. Do you want to save it now? - Проект был восстановлен из предыдущей сессии. Сейчас он не сохранён и будет потерян, если его не сохранить. -Хотите сохранить его сейчас? - - - LMMS Project - ЛММС Проект - - - LMMS Project Template - Шаблон ЛММС Проекта - - - Overwrite default template? - Перезаписать обычный шаблон? - - - This will overwrite your current default template. - Это перезапишет текущий обычный шаблон. - - - Smooth scroll - Плавная прокрутка - - - Enable note labels in piano roll - Включить обозначение нот в музыкальном редакторе - - - Save project template - - - + Volume as dBFS - Could not open file - Не могу открыть файл + + Smooth scroll + Плавная прокрутка - Could not open file %1 for writing. -Please make sure you have write permission to the file and the directory containing the file and try again! - Невозможно открыть файл %1 для записи. Пожалуйста, убедитесь, что у вас есть разрешение на запись в файл и содержащую его директорию, и попробуйте снова. - - - Export &MIDI... - Экспорт &MIDI... + + Enable note labels in piano roll + Включить обозначение нот в музыкальном редакторе MeterDialog + + Meter Numerator Шкала чисел + + Meter Denominator Шкала делений + TIME SIG ПЕРИОД @@ -4163,10 +5177,12 @@ Please make sure you have write permission to the file and the directory contain MeterModel + Numerator Числитель + Denominator Знаменатель @@ -4174,10 +5190,12 @@ Please make sure you have write permission to the file and the directory contain MidiController + MIDI Controller Контроллер MIDI + unnamed_midi_controller нераспознанный миди контроллер @@ -4185,86 +5203,105 @@ Please make sure you have write permission to the file and the directory contain MidiImport + + Setup incomplete установка не завершена + You do not have set up a default soundfont in the settings dialog (Edit->Settings). Therefore no sound will be played back after importing this MIDI file. You should download a General MIDI soundfont, specify it in settings dialog and try again. Вы не установили SoundFont по умолчанию в параметрах (Правка->Настройки), поэтому после импорта миди файла звук воспроизводиться не будет. Вам следует загрузить основной MiDi SoundFont, указать его в параметрах и попробовать снова. + You did not compile LMMS with support for SoundFont2 player, which is used to add default sound to imported MIDI files. Therefore no sound will be played back after importing this MIDI file. Вы не включили поддержку проигрывателя SoundFont2 при компиляции ЛММС, он используется для добавления основного звука в импортируемые Миди файлы, поэтому звука не будет после импорта этого миди файла. + Track - + Дорожка MidiJack + JACK server down When JACK(JACK Audio Connection Kit) disconnects, it will show the following message (title) JACK-сервер не доступен + The JACK server seems to be shuted down. When JACK(JACK Audio Connection Kit) disconnects, it will show the following message (dialog message) - + JACK-сервер, похоже, не запущен. MidiPort + Input channel Вход + Output channel Выход + Input controller Контроллер входа + Output controller Контроллер выхода + Fixed input velocity Постоянная скорость ввода + Fixed output velocity Постоянная скорость вывода - Output MIDI program - Программа для вывода MiDi - - - Receive MIDI-events - Принимать события MIDI - - - Send MIDI-events - Отправлять события MIDI - - + Fixed output note Постоянный вывод нот + + Output MIDI program + Программа для вывода MiDi + + + Base velocity Базовая скорость + + + Receive MIDI-events + Принимать события MIDI + + + + Send MIDI-events + Отправлять события MIDI + MidiSetupWidget + DEVICE УСТРОЙСТВО @@ -4272,474 +5309,595 @@ Please make sure you have write permission to the file and the directory contain MonstroInstrument + Osc 1 Volume - + Осциллятор 1 громкость + Osc 1 Panning - + Осциллятор 1 баланс + Osc 1 Coarse detune + Osc 1 Fine detune left + Osc 1 Fine detune right + Osc 1 Stereo phase offset + Osc 1 Pulse width + Osc 1 Sync send on rise + Osc 1 Sync send on fall + Osc 2 Volume - + Осциллятор 2 громкость + Osc 2 Panning - + Осциллятор 2 баланс + Osc 2 Coarse detune + Osc 2 Fine detune left + Osc 2 Fine detune right + Osc 2 Stereo phase offset + Osc 2 Waveform + Osc 2 Sync Hard + Osc 2 Sync Reverse + Osc 3 Volume - + Осциллятор 3 громкость + Osc 3 Panning - + Осциллятор 3 баланс + Osc 3 Coarse detune + Osc 3 Stereo phase offset + Osc 3 Sub-oscillator mix + Osc 3 Waveform 1 + Osc 3 Waveform 2 + Osc 3 Sync Hard + Osc 3 Sync Reverse + LFO 1 Waveform + LFO 1 Attack + LFO 1 Rate + LFO 1 Phase + LFO 2 Waveform + LFO 2 Attack + LFO 2 Rate + LFO 2 Phase + Env 1 Pre-delay + Env 1 Attack + Env 1 Hold + Env 1 Decay + Env 1 Sustain + Env 1 Release + Env 1 Slope + Env 2 Pre-delay + Env 2 Attack + Env 2 Hold + Env 2 Decay + Env 2 Sustain + Env 2 Release + Env 2 Slope - + Кривая 2 Наклон + Osc2-3 modulation + Selected view - + Выбранный вид + Vol1-Env1 + Vol1-Env2 + Vol1-LFO1 + Vol1-LFO2 + Vol2-Env1 + Vol2-Env2 + Vol2-LFO1 + Vol2-LFO2 + Vol3-Env1 + Vol3-Env2 + Vol3-LFO1 + Vol3-LFO2 + Phs1-Env1 + Phs1-Env2 + Phs1-LFO1 + Phs1-LFO2 + Phs2-Env1 + Phs2-Env2 + Phs2-LFO1 + Phs2-LFO2 + Phs3-Env1 + Phs3-Env2 + Phs3-LFO1 + Phs3-LFO2 + Pit1-Env1 + Pit1-Env2 + Pit1-LFO1 + Pit1-LFO2 + Pit2-Env1 + Pit2-Env2 + Pit2-LFO1 + Pit2-LFO2 + Pit3-Env1 + Pit3-Env2 + Pit3-LFO1 + Pit3-LFO2 + PW1-Env1 + PW1-Env2 + PW1-LFO1 + PW1-LFO2 + Sub3-Env1 + Sub3-Env2 + Sub3-LFO1 + Sub3-LFO2 + + Sine wave Синусоида + Bandlimited Triangle wave Ограниченная по частоте треугольная волна + Bandlimited Saw wave Ограниченная по частоте острая волна + Bandlimited Ramp wave - + Ограничение по частоте ниспадающая волна + Bandlimited Square wave Ограниченная по частоте квадратная волна + Bandlimited Moog saw wave - Ограниченная по частоте Муг острая волна + Ограниченная по частоте Муг-зигзаг волна + + Soft square wave Сглаженная квадратная волна + Absolute sine wave + + Exponential wave Экспоненциальная волна + White noise Белый шум + Digital Triangle wave Цифровая треугольная волна + Digital Saw wave Цифровая острая волна + Digital Ramp wave + Digital Square wave Цифровая квадратная волна + Digital Moog saw wave Цифровая Муг острая волна + Triangle wave Треугольная волна + Saw wave Зигзаг + Ramp wave + Square wave Квадрат + Moog saw wave + Abs. sine wave + Random Случайно + Random smooth Случайное сглаживание @@ -4747,10 +5905,12 @@ Please make sure you have write permission to the file and the directory contain MonstroView + Operators view Операторский вид + The Operators view contains all the operators. These include both audible operators (oscillators) and inaudible operators, or modulators: Low-frequency oscillators and Envelopes. Knobs and other widgets in the Operators view have their own what's this -texts, so you can get more specific help for them that way. @@ -4759,10 +5919,12 @@ Knobs and other widgets in the Operators view have their own what's this -t Регуляторы и другие виджеты в Операторском виде имеют свои подписи "Что это?", можно получить по ним более детальную справку таким образом. + Matrix view Матричный вид + The Matrix view contains the modulation matrix. Here you can define the modulation relationships between the various operators: Each audible operator (oscillators 1-3) has 3-4 properties that can be modulated by any of the modulators. Using more modulations consumes more CPU power. The view is divided to modulation targets, grouped by the target oscillator. Available targets are volume, pitch, phase, pulse width and sub-osc ratio. Note: some targets are specific to one oscillator only. @@ -4775,80 +5937,266 @@ Each modulation target has 4 knobs, one for each modulator. By default the knobs Каждая цель модуляции имеет 4 регулятора, один на каждый модулятор. По умолчанию регуляторы установлены на 0, то есть без модуляции. Включая регулятор на 1 ведёт к тому, что модулятор влияет на цель модуляции на столько на сколько возможно. Включая его на -1 делает то же, но с обратной модуляцией. + + + + Volume + Громкость + + + + + + Panning + Баланс + + + + + + Coarse detune + Грубая расстройка + + + + + + semitones + полутона + + + + + Finetune left + + + + + + + + cents + + + + + + Finetune right + + + + + + + Stereo phase offset + Сдвиг стерео фазы + + + + + + + + deg + град + + + + Pulse width + Длительность импульса + + + + Send sync on pulse rise + Выдача синхронизации по нарастанию импульса + + + + Send sync on pulse fall + Выдача синхронизации по спаду импульса + + + + Hard sync oscillator 2 + + + + + Reverse sync oscillator 2 + + + + + Sub-osc mix + + + + + Hard sync oscillator 3 + + + + + Reverse sync oscillator 3 + + + + + + + + Attack + Вступление + + + + + Rate + Частота выборки + + + + + Phase + + + + + + Pre-delay + Пре-дилэй + + + + + Hold + Удерживание + + + + + Decay + Затихание + + + + + Sustain + Выдержка + + + + + Release + Убывание + + + + + Slope + Фронт + + + Mix Osc2 with Osc3 Смешать Осц2 с Осц3 + Modulate amplitude of Osc3 with Osc2 Модулировать амплитуду осциллятора 3 сигналом с осц2 + Modulate frequency of Osc3 with Osc2 Модулировать частоту осциллятора 3 сигналом с осц2 + Modulate phase of Osc3 with Osc2 Модулировать фазу Осц3 осциллятором2 + The CRS knob changes the tuning of oscillator 1 in semitone steps. Регулятор CRS меняет настройку осциллятора 1 в размере полутона. + The CRS knob changes the tuning of oscillator 2 in semitone steps. Регулятор CRS меняет настройку осциллятора 2 в размере полутона. + The CRS knob changes the tuning of oscillator 3 in semitone steps. Регулятор CRS меняет настройку осциллятора 3 в размере полутона. + + + + FTL and FTR change the finetuning of the oscillator for left and right channels respectively. These can add stereo-detuning to the oscillator which widens the stereo image and causes an illusion of space. FTL и FTR меняют подстройку осциллятора для левого и правого канала соответственно. Они могут добавить стерео расстраивания осциллятора, которое расширяет стерео картину и создаёт иллюзию космоса. + + + The SPO knob modifies the difference in phase between left and right channels. Higher difference creates a wider stereo image. Регулятор SPO меняет фазовую разницу между левым и правым каналами. Высокая разница создаёт более широкую стерео картину. + The PW knob controls the pulse width, also known as duty cycle, of oscillator 1. Oscillator 1 is a digital pulse wave oscillator, it doesn't produce bandlimited output, which means that you can use it as an audible oscillator but it will cause aliasing. You can also use it as an inaudible source of a sync signal, which can be used to synchronize oscillators 2 and 3. PW регулятор контролирует ширину пульсаций, также известную как рабочий цикл осциллятора 1. Осциллятор 1 это цифровой импульсный волновой генератор, он не воспроизводит сигнал с ограниченной полосой, это значит, что его можно использовать как слышимый осциллятор, но приведёт к наложению сигналов (или сглаживанию). Его можно использовать и как не слышимый источник синхронизирующего сигнала, для использования в синхронизации осцилляторов 2 и 3. + Send Sync on Rise: When enabled, the Sync signal is sent every time the state of oscillator 1 changes from low to high, ie. when the amplitude changes from -1 to 1. Oscillator 1's pitch, phase and pulse width may affect the timing of syncs, but its volume has no effect on them. Sync signals are sent independently for both left and right channels. Посылать синхронизацию при повышении: при включении, сигнал синхронизации посылается каждый раз когда состояние осциллятора 1 меняется с низкого на высокое, т.е. когда амплитуда меняется от -1 до 1. Тон осциллятора 1, фаза и ширина пульсаций может влиять на время синхронизации, но громкость не имеет эффекта. Сигнал синхронизации посылается независимо для левого и правого каналов. + Send Sync on Fall: When enabled, the Sync signal is sent every time the state of oscillator 1 changes from high to low, ie. when the amplitude changes from 1 to -1. Oscillator 1's pitch, phase and pulse width may affect the timing of syncs, but its volume has no effect on them. Sync signals are sent independently for both left and right channels. Посылать синхронизацию при падении: при включении, сигнал синхронизации посылается каждый раз когда состояние осциллятора 1 меняется с выского на низкое, т.е. когда амплитуда меняется от 1 до -1. Тон осциллятора 1, фаза и ширина пульсаций может влиять на время синхронизации, но громкость не имеет эффекта. Сигнал синхронизации посылается независимо для левого и правого каналов. + + Hard sync: Every time the oscillator receives a sync signal from oscillator 1, its phase is reset to 0 + whatever its phase offset is. Жесткая синхр. : Каждый раз при получении осциллятором сигнала синхронизации от осциллятора 1, его фаза сбрасывается до 0 + его граница фазы, какой бы она ни была. + + Reverse sync: Every time the oscillator receives a sync signal from oscillator 1, the amplitude of the oscillator gets inverted. Обратная синхронизация: Каждый раз при получении сигнала синхронизации от осциллятора 1, амплитуда осцилятора переворачивается. + Choose waveform for oscillator 2. Выбрать форму волны для осциллятора 2. + Choose waveform for oscillator 3's first sub-osc. Oscillator 3 can smoothly interpolate between two different waveforms. Выберите форму волны для первого доп. осциллятора осциллятора 3. Осциллятор 3 может мягко переходить между двумя разными волнами. + Choose waveform for oscillator 3's second sub-osc. Oscillator 3 can smoothly interpolate between two different waveforms. Выберите форму волны для второго доп. осциллятора осциллятора 3. Осциллятор 3 может мягко переходить между двумя разными волнами. + The SUB knob changes the mixing ratio of the two sub-oscs of oscillator 3. Each sub-osc can be set to produce a different waveform, and oscillator 3 can smoothly interpolate between them. All incoming modulations to oscillator 3 are applied to both sub-oscs/waveforms in the exact same way. SUB меняет смешивание двух доп. осяцилляторов осциллятора 3. Каждый доп. осц. может быть установлен для создания разных волн и осциллятор 3 может мягко переходить между ними. Все входящие модуляции для осциллятора 3 применяются на оба доп.осц./волны одним и тем же образом. + In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. Mix mode means no modulation: the outputs of the oscillators are simply mixed together. @@ -4857,6 +6205,7 @@ Mix mode means no modulation: the outputs of the oscillators are simply mixed to Смешанный (Mix) режим значит без модуляции: выходы осцилляторов просто смешиваются друг с другом. + In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. AM means amplitude modulation: Oscillator 3's amplitude (volume) is modulated by oscillator 2. @@ -4865,6 +6214,7 @@ AM means amplitude modulation: Oscillator 3's amplitude (volume) is modulat AM режим значит Амплитуда Модуляции: Осциллятор 2 модулирует амплитуду (громкость) осциллятора 3. + In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. FM means frequency modulation: Oscillator 3's frequency (pitch) is modulated by oscillator 2. The frequency modulation is implemented as phase modulation, which gives a more stable overall pitch than "pure" frequency modulation. @@ -4873,6 +6223,7 @@ FM means frequency modulation: Oscillator 3's frequency (pitch) is modulate FM (ЧМ) режим значит Частотная Модуляция: Осциллятор 2 модулирует частоту (pitch, тональность) осциллятора 3. Частота модуляции происходит в фазе модуляции, которая даёт более стабильный общий тон, чем "чистая" частотная модуляция. + In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. PM means phase modulation: Oscillator 3's phase is modulated by oscillator 2. It differs from frequency modulation in that the phase changes are not cumulative. @@ -4881,6 +6232,7 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator PM (ФМ) режим значит фазовая модуляция: Осциллятор 2 модулирует фазу осциллятора 3. Это отличается от частотной модуляции тем, что изменения фаз не суммируются. + Select the waveform for LFO 1. "Random" and "Random smooth" are special waveforms: they produce random output, where the rate of the LFO controls how often the state of the LFO changes. The smooth version interpolates between these states with cosine interpolation. These random modes can be used to give "life" to your presets - add some of that analog unpredictability... Выберите форму волны для LFO 1 (НизкоЧастотныйГенератор). @@ -4888,6 +6240,7 @@ PM (ФМ) режим значит фазовая модуляция: Осцил Сглаженная версия переходит между этими состояниями с косинусоидальной интерплояцией. Эти случайные режимы могут быть использованы, чтобы дать "жизни" вашим настройкам - добавить немного аналоговой непредсказуемости... + Select the waveform for LFO 2. "Random" and "Random smooth" are special waveforms: they produce random output, where the rate of the LFO controls how often the state of the LFO changes. The smooth version interpolates between these states with cosine interpolation. These random modes can be used to give "life" to your presets - add some of that analog unpredictability... Выберите форму волны для LFO 2 (НизкоЧастотныйГенератор). @@ -4895,150 +6248,110 @@ PM (ФМ) режим значит фазовая модуляция: Осцил Сглаженная версия переходит между этими состояниями с косинусоидальной интерплояцией. Эти случайные режимы могут быть использованы, чтобы дать "жизни" вашим настройкам - добавить немного аналоговой непредсказуемости... + + Attack causes the LFO to come on gradually from the start of the note. Атака отвечает за плавность поведения LFO от начала ноты. + + Rate sets the speed of the LFO, measured in milliseconds per cycle. Can be synced to tempo. Rate (Частота) устанавливает скорость LFO, измеряемую в миллисекундах за цикл. Может синхронизироваться с темпом. + + PHS controls the phase offset of the LFO. PHS контролирует сдвиг фазы LFO (НЧГ). + + PRE, or pre-delay, delays the start of the envelope from the start of the note. 0 means no delay. PRE предзадержка, задерживает старт огибающей от начала ноты. 0 значит без задержки. + + ATT, or attack, controls how fast the envelope ramps up at start, measured in milliseconds. A value of 0 means instant. ATT атака контролирует как быстро огибающая наращивается на старте, измеряясь в милисекундах. Значение 0 значит мгновенно. + + HOLD controls how long the envelope stays at peak after the attack phase. HOLD (УДЕРЖ) контролирует как долго огибающая остаётся на пике после фазы атаки. + + DEC, or decay, controls how fast the envelope falls off from its peak, measured in milliseconds it would take to go from peak to zero. The actual decay may be shorter if sustain is used. DEC (decay) затухание контролирует как быстро огибающая спадает с пикового значения, измеряется в милисекундах, как долго будет идти с пика до нуля. Реальное затухание может быть короче, если используется выдержка. + + SUS, or sustain, controls the sustain level of the envelope. The decay phase will not go below this level as long as the note is held. SUS (sustain) выдержка, контролирует уровень огибающей. Затухание фазы не пойдёт ниже этого уровня пока нота удерживается. + + REL, or release, controls how long the release is for the note, measured in how long it would take to fall from peak to zero. Actual release may be shorter, depending on at what phase the note is released. REL (release) отпуск контролирует как долго нота отпускается, измеряясь в долготе падения от пика до нуля. Реальный отпуск может быть короче, в зависимости от фазы, в которой нота отпущена. + + The slope knob controls the curve or shape of the envelope. A value of 0 creates straight rises and falls. Negative values create curves that start slowly, peak quickly and fall of slowly again. Positive values create curves that start and end quickly, and stay longer near the peaks. Регулятор наклона контролирует кривую или образ огибающей. Значение 0 создаёт прямые подъёмы и спады. Отрицательные величины создают кривые с замедленным началом, быстрым пиком и снова замедленным спадом. Позитивные значения создают кривые которые начинаются и кончаются быстро, но долбше остаются на пиках. - Volume - Громкость - - - Panning - Баланс - - - Coarse detune - - - - semitones - полутона - - - Finetune left - - - - cents - - - - Finetune right - - - - Stereo phase offset - Сдвиг стерео фазы - - - deg - - - - Pulse width - Длительность импульса - - - Send sync on pulse rise - - - - Send sync on pulse fall - - - - Hard sync oscillator 2 - - - - Reverse sync oscillator 2 - - - - Sub-osc mix - - - - Hard sync oscillator 3 - - - - Reverse sync oscillator 3 - - - - Attack - Вступление - - - Rate - Частота выборки - - - Phase - - - - Pre-delay - - - - Hold - Удерживание - - - Decay - Затихание - - - Sustain - Выдержка - - - Release - Убывание - - - Slope - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Modulation amount Глубина модуляции @@ -5046,34 +6359,42 @@ PM (ФМ) режим значит фазовая модуляция: Осцил MultitapEchoControlDialog + Length Длина + Step length: - + Длина шага: + Dry - + Высушить + Dry Gain: + Stages + Lowpass stages: + Swap inputs - + Переставить входы местами + Swap left and right input channel for reflections Поменять вход левого и правого канала для отзвуков @@ -5081,82 +6402,102 @@ PM (ФМ) режим значит фазовая модуляция: Осцил NesInstrument + Channel 1 Coarse detune - + Канал 1 - грубая расстройка + Channel 1 Volume Громкость 1 канала + Channel 1 Envelope length - + Канал 1 - Длина огибающей + Channel 1 Duty cycle + Channel 1 Sweep amount + Channel 1 Sweep rate + Channel 2 Coarse detune + Channel 2 Volume Громкость 2 канала + Channel 2 Envelope length + Channel 2 Duty cycle + Channel 2 Sweep amount + Channel 2 Sweep rate + Channel 3 Coarse detune + Channel 3 Volume Громкость 3 канала + Channel 4 Volume Громкость 4 канала + Channel 4 Envelope length + Channel 4 Noise frequency + Channel 4 Noise frequency sweep + Master volume Основная громкость + Vibrato Вибрато @@ -5164,114 +6505,155 @@ PM (ФМ) режим значит фазовая модуляция: Осцил NesInstrumentView + + + + Volume Громкость + + + Coarse detune - + Грубая расстройка + + + Envelope length - + Длина огибающей + Enable channel 1 - + Включить канал 1 + Enable envelope 1 - + Включить кривую 1 + Enable envelope 1 loop + Enable sweep 1 + + Sweep amount - + Амплитуда биений + + Sweep rate - + Частота биений + + 12.5% Duty cycle - + 12.5% Рабочий цикл + + 25% Duty cycle - + 25% Рабочий цикл + + 50% Duty cycle - + 50% Рабочий цикл + + 75% Duty cycle - + 75% Рабочий цикл + Enable channel 2 - + Включить канал 2 + Enable envelope 2 - + Включить кривую 2 + Enable envelope 2 loop - + Включить повтор кривой 2 + Enable sweep 2 + Enable channel 3 + Noise Frequency - + Частота шума + Frequency sweep + Enable channel 4 + Enable envelope 4 + Enable envelope 4 loop + Quantize noise frequency when using note frequency + Use note frequency for noise - + Использовние частоты ноты для шума + Noise mode - + Режим шума + Master Volume - + Мастер-громкость + Vibrato Вибрато @@ -5279,81 +6661,103 @@ PM (ФМ) режим значит фазовая модуляция: Осцил OscillatorObject - Osc %1 volume - Громкость осциллятора %1 - - - Osc %1 panning - Стереобаланс для осциллятора %1 - - - Osc %1 coarse detuning - Подстройка осциллятора %1 грубая - - - Osc %1 fine detuning left - Подстройка левого канала осциллятора %1 тонкая - - - Osc %1 fine detuning right - Подстройка правого канала осциллятора %1 тонкая - - - Osc %1 phase-offset - Сдвиг фазы для осциллятора %1 - - - Osc %1 stereo phase-detuning - Подстройка стерео-фазы осциллятора %1 - - - Osc %1 wave shape - Гладкость сигнала осциллятора %1 - - - Modulation type %1 - Тип модуляции %1 - - + Osc %1 waveform Форма сигнала осциллятора %1 + Osc %1 harmonic Осц %1 гармонический + + + + Osc %1 volume + Громкость осциллятора %1 + + + + + Osc %1 panning + Стереобаланс для осциллятора %1 + + + + + Osc %1 fine detuning left + Подстройка левого канала осциллятора %1 тонкая + + + + Osc %1 coarse detuning + Подстройка осциллятора %1 грубая + + + + Osc %1 fine detuning right + Подстройка правого канала осциллятора %1 тонкая + + + + Osc %1 phase-offset + Сдвиг фазы для осциллятора %1 + + + + Osc %1 stereo phase-detuning + Подстройка стерео-фазы осциллятора %1 + + + + Osc %1 wave shape + Гладкость сигнала осциллятора %1 + + + + Modulation type %1 + Тип модуляции %1 + PatchesDialog + Qsynth: Channel Preset + Bank selector - + Выбор банка + Bank Банк + Program selector Выбор программ + Patch Патч + Name Имя + OK ОК + Cancel Отмена @@ -5361,46 +6765,57 @@ PM (ФМ) режим значит фазовая модуляция: Осцил PatmanView + Open other patch Открыть другой патч + Click here to open another patch-file. Loop and Tune settings are not reset. Нажмите чтобы открыть другой патч-файл. Цикличность и настройки при этом сохранятся. + Loop Повтор + Loop mode Режим повтора + Here you can toggle the Loop mode. If enabled, PatMan will use the loop information available in the file. Здесь включается/выключается режим повтора, при включёнии PatMan будет использовать информацию о повторе из файла. + Tune Подстроить + Tune mode Тип подстройки + Here you can toggle the Tune mode. If enabled, PatMan will tune the sample to match the note's frequency. Здесь включается/выключается режим подстройки. Если он включён, то PatMan изменит запись так, чтобы она совпадала по частоте с нотой. + No file selected Не выбран файл + Open patch file Открыть патч-файл + Patch-Files (*.pat) Патч-файлы (*.pat) @@ -5408,30 +6823,47 @@ PM (ФМ) режим значит фазовая модуляция: Осцил PatternView + + use mouse wheel to set velocity of a step + + + + + double-click to open in Piano Roll + Двойной щелчок открывает в Редакторе Нот + + + Open in piano-roll Открыть в редакторе нот + Clear all notes Очистить все ноты + Reset name Сбросить название + Change name Переименовать + Add steps Добавить такты + Remove steps Удалить такты + Clone Steps Клонировать такты @@ -5439,14 +6871,17 @@ PM (ФМ) режим значит фазовая модуляция: Осцил PeakController + Peak Controller Контроллер вершин + Peak Controller Bug Контроллер вершин с багом + Due to a bug in older version of LMMS, the peak controllers may not be connect properly. Please ensure that peak controllers are connected properly and re-save this file. Sorry for any inconvenience caused. Из-за ошибки в старой версии LMMS контроллеры вершин не могут правильно подключаться. Пж. убедитесь, что контроллеры вершин правильно подсоединены и пересохраните этот файл, извините, за причинённые неудобства. @@ -5454,10 +6889,12 @@ PM (ФМ) режим значит фазовая модуляция: Осцил PeakControllerDialog + PEAK ПИК + LFO Controller Контроллер LFO @@ -5465,307 +6902,383 @@ PM (ФМ) режим значит фазовая модуляция: Осцил PeakControllerEffectControlDialog + BASE БАЗА + Base amount: Базовое значение: - Modulation amount: - Глубина модуляции: - - - Attack: - Вступление: - - - Release: - Убывание: - - + AMNT ГЛУБ + + Modulation amount: + Глубина модуляции: + + + MULT МНОЖ + Amount Multiplicator: Величина множителя: + ATCK ВСТУП + + Attack: + Вступление: + + + DCAY СПАД - Treshold: - + + Release: + Убывание: + TRSH - + ПОР + + + + Treshold: + Порог: PeakControllerEffectControls + Base value Опорное значение + Modulation amount Глубина модуляции - Mute output - Заглушить вывод - - + Attack Вступление + Release Убывание + + Treshold + Порог + + + + Mute output + Заглушить вывод + + + Abs Value Абс значение + Amount Multiplicator Величина множителя - - Treshold - - PianoRoll - Please open a pattern by double-clicking on it! - Откройте мелодию с помощью двойного щелчка мышью! - - - Last note - По посл. ноте - - - Note lock - Фиксация нот - - + Note Velocity Громкость нот + Note Panning Стереофония нот + Mark/unmark current semitone Отметить/Снять отметку с текущего полутона - Mark current scale - Отметить текущий подъём - - - Mark current chord - Отметить текущий аккорд - - - Unmark all - Снять выделение - - - No scale - Без подъёма - - - No chord - Убрать аккорды - - - Velocity: %1% - Громкость %1% - - - Panning: %1% left - Баланс: %1% лево - - - Panning: %1% right - Баланс: %1% право - - - Panning: center - Баланс: центр - - - Please enter a new value between %1 and %2: - Введите новое значение от %1 до %2: - - + Mark/unmark all corresponding octave semitones Отметить/Снять отметку со всех соответствующих октав полутонов + + Mark current scale + Отметить текущий подъём + + + + Mark current chord + Отметить текущий аккорд + + + + Unmark all + Снять выделение + + + Select all notes on this key Выбрать все ноты по этой кнопке + + + Note lock + Фиксация нот + + + + Last note + По посл. ноте + + + + No scale + Без подъёма + + + + No chord + Убрать аккорды + + + + Velocity: %1% + Громкость %1% + + + + Panning: %1% left + Баланс: %1% лево + + + + Panning: %1% right + Баланс: %1% право + + + + Panning: center + Баланс: центр + + + + Please open a pattern by double-clicking on it! + Откройте мелодию с помощью двойного щелчка мышью! + + + + + Please enter a new value between %1 and %2: + Введите новое значение от %1 до %2: + PianoRollWindow + Play/pause current pattern (Space) Игра/Пауза текущей мелодии (Пробел) + Record notes from MIDI-device/channel-piano Записать ноты с музыкального инструмента (MIDI)/канала + Record notes from MIDI-device/channel-piano while playing song or BB track Записать ноты с цифрового музыкального инструмента (MIDI) во время воспроизведения композиции или дорожки Ритм-Баса + Stop playing of current pattern (Space) Остановить воспроизведение текущей мелодии (Пробел) + Click here to play the current pattern. This is useful while editing it. The pattern is automatically looped when its end is reached. Нажмите здесь чтобы проиграть текущую мелодию. Это может пригодиться при её редактировании. По окончании мелодии воспроизведение начнётся сначала. + Click here to record notes from a MIDI-device or the virtual test-piano of the according channel-window to the current pattern. When recording all notes you play will be written to this pattern and you can play and edit them afterwards. Нажмите эту кнопку, если вы хотите записать ноты с устройства MIDI или виртуального синтезатора соответствующего канала. Позже вы сможете отредактировать записанную мелодию. + Click here to record notes from a MIDI-device or the virtual test-piano of the according channel-window to the current pattern. When recording all notes you play will be written to this pattern and you will hear the song or BB track in the background. Нажмите эту кнопку, если вы хотите записать ноты с устройства MIDI или виртуального синтезатора соответствующего канала. Во время записи все ноты записываются в эту мелодию, и вы будете слышать композицию или РБ дорожку на заднем плане. + Click here to stop playback of current pattern. Нажмите здесь, если вы хотите остановить воспроизведение текущей мелодии. + + Edit actions + Правка: + + + Draw mode (Shift+D) Режим рисования (Shift+D) + Erase mode (Shift+E) Режим стирания (Shift+E) + Select mode (Shift+S) Режим выбора нот (Shift+S) - Detune mode (Shift+T) - Режим подстраивания (Shift+T) - - + Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold %1 to temporarily go into select mode. Режим рисования нот, в нём вы можете добавлять/перемещать и изменять длительность одиночных нот. Это режим по умолчанию и используется большую часть времени. Для включения этого режима можно использовать комбинацию клавиш Shift+D, удерживайте %1 для временного переключения в режим выбора. + Click here and erase mode will be activated. In this mode you can erase notes. You can also press 'Shift+E' on your keyboard to activate this mode. Режим стирания. В этом режиме вы можете стирать ноты. Для включения этого режима можно использовать комбинацию клавиш Shift+E. + Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold %1 in draw mode to temporarily use select mode. Режим выделения. В этом режиме можно выделять ноты, можно также удерживать %1 в режиме рисования, чтобы можно было на время войти в режим выделения. - Click here and detune mode will be activated. In this mode you can click a note to open its automation detuning. You can utilize this to slide notes from one to another. You can also press 'Shift+T' on your keyboard to activate this mode. - Режим подстройки. В этом режиме можно выбирать ноты для автоматизации их подстраивания. Можно использовать это для переходов нот от одной к другой. Для активации с клавиатуры <Shift+T>. + + Pitch Bend mode (Shift+T) + - Cut selected notes (%1+X) - Переместить выделенные ноты в буфер (%1+X) + + Click here and Pitch Bend mode will be activated. In this mode you can click a note to open its automation detuning. You can utilize this to slide notes from one to another. You can also press 'Shift+T' on your keyboard to activate this mode. + Нажмите здесь для активации Pitch Blend режима. Вы сможете кликнуть на ноту, чтобы начать автоматическией детюн. Можно использовать это для "скольжения" от одной ноты к другой. Можно включить этот режим при помощи Shift + T. - Copy selected notes (%1+C) - Копировать выделенные ноты в буфер (%1+X) - - - Paste notes from clipboard (%1+V) - Вставить ноты из буфера (%1+V) - - - Click here and the selected notes will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. - При нажатии на эту кнопку выделеные ноты будут вырезаны в буфер. Позже вы можете вставить их в любое место любой мелодии с помощью кнопки "Вставить". - - - Click here and the selected notes will be copied into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. - При нажатии на эту кнопку выделеные ноты будут скопированы в буфер. Позже вы можете вставить их в любое место любой мелодии с помощью кнопки "Вставить". - - - Click here and the notes from the clipboard will be pasted at the first visible measure. - При нажатии на эту кнопку ноты из буфера будут вставлены в первый видимый такт. - - - This controls the magnification of an axis. It can be helpful to choose magnification for a specific task. For ordinary editing, the magnification should be fitted to your smallest notes. - Этим контролируется масштаб оси. Это может быть полезно для специальных задач. Для обычного редактирования, масштаб следует устанавливать по наименьшей ноте. - - - The 'Q' stands for quantization, and controls the grid size notes and control points snap to. With smaller quantization values, you can draw shorter notes in Piano Roll, and more exact control points in the Automation Editor. - "Q" обозначает квантизацию и контролирует размер нотной сетки и контрольные точки притяжения. С меньшей величиной квантизации, можно рисовать короткие ноты в редаторе нот и более точно контролировать точки в Редакторе Автоматизации. - - - This lets you select the length of new notes. 'Last Note' means that LMMS will use the note length of the note you last edited - Позволяет выбрть длину новой ноты. "Последняя Нота" значит, что LMMS будет использовать длину ноты, изменённой в последний раз - - - The feature is directly connected to the context-menu on the virtual keyboard, to the left in Piano Roll. After you have chosen the scale you want in this drop-down menu, you can right click on a desired key in the virtual keyboard, and then choose 'Mark current Scale'. LMMS will highlight all notes that belongs to the chosen scale, and in the key you have selected! - Функция напрямую связана с контекстным меню на виртуальной клавиатуре слева в нотном редакторе. После того, как выбран масштаб в выпадающем меню, можно кликнуть правой кнопкой в виртуальной клавиатуре и выбрать "Mark Current Scale" (Отметить текущий масштаб). LMMS подсветит все ноты лежащие в выбранном масштабе для выбранной клавиши! - - - Let you select a chord which LMMS then can draw or highlight.You can find the most common chords in this drop-down menu. After you have selected a chord, click anywhere to place the chord, and right click on the virtual keyboard to open context menu and highlight the chord. To return to single note placement, you need to choose 'No chord' in this drop-down menu. - Позволяет выбрать аккорд, который LMMS затем сможет нарисовать или подсветить. В этом меню можно найти ниболее популярные аккорды. После того, как вы выбрали аккорд, кликните в любом месте, чтобы поставить его и правым кликом по виртуальной клавиатуре открывается контекстное меню и подсветка аккорда. Для возврата в режим одной ноты нужно выбрать "Без аккорда" в этом выпадающем меню. - - - Edit actions - Правка: + + Quantize + + Copy paste controls Копировать-вставить управление + + Cut selected notes (%1+X) + Переместить выделенные ноты в буфер (%1+X) + + + + Copy selected notes (%1+C) + Копировать выделенные ноты в буфер (%1+X) + + + + Paste notes from clipboard (%1+V) + Вставить ноты из буфера (%1+V) + + + + Click here and the selected notes will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. + При нажатии на эту кнопку выделеные ноты будут вырезаны в буфер. Позже вы можете вставить их в любое место любой мелодии с помощью кнопки "Вставить". + + + + Click here and the selected notes will be copied into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. + При нажатии на эту кнопку выделеные ноты будут скопированы в буфер. Позже вы можете вставить их в любое место любой мелодии с помощью кнопки "Вставить". + + + + Click here and the notes from the clipboard will be pasted at the first visible measure. + При нажатии на эту кнопку ноты из буфера будут вставлены в первый видимый такт. + + + Timeline controls Управление временем + Zoom and note controls - + Контроль нот и увеличения. + + This controls the magnification of an axis. It can be helpful to choose magnification for a specific task. For ordinary editing, the magnification should be fitted to your smallest notes. + Этим контролируется масштаб оси. Это может быть полезно для специальных задач. Для обычного редактирования, масштаб следует устанавливать по наименьшей ноте. + + + + The 'Q' stands for quantization, and controls the grid size notes and control points snap to. With smaller quantization values, you can draw shorter notes in Piano Roll, and more exact control points in the Automation Editor. + "Q" обозначает квантизацию и контролирует размер нотной сетки и контрольные точки притяжения. С меньшей величиной квантизации, можно рисовать короткие ноты в редаторе нот и более точно контролировать точки в Редакторе Автоматизации. + + + + This lets you select the length of new notes. 'Last Note' means that LMMS will use the note length of the note you last edited + Позволяет выбрть длину новой ноты. "Последняя Нота" значит, что LMMS будет использовать длину ноты, изменённой в последний раз + + + + The feature is directly connected to the context-menu on the virtual keyboard, to the left in Piano Roll. After you have chosen the scale you want in this drop-down menu, you can right click on a desired key in the virtual keyboard, and then choose 'Mark current Scale'. LMMS will highlight all notes that belongs to the chosen scale, and in the key you have selected! + Функция напрямую связана с контекстным меню на виртуальной клавиатуре слева в нотном редакторе. После того, как выбран масштаб в выпадающем меню, можно кликнуть правой кнопкой в виртуальной клавиатуре и выбрать "Mark Current Scale" (Отметить текущий масштаб). LMMS подсветит все ноты лежащие в выбранном масштабе для выбранной клавиши! + + + + Let you select a chord which LMMS then can draw or highlight.You can find the most common chords in this drop-down menu. After you have selected a chord, click anywhere to place the chord, and right click on the virtual keyboard to open context menu and highlight the chord. To return to single note placement, you need to choose 'No chord' in this drop-down menu. + Позволяет выбрать аккорд, который LMMS затем сможет нарисовать или подсветить. В этом меню можно найти ниболее популярные аккорды. После того, как вы выбрали аккорд, кликните в любом месте, чтобы поставить его и правым кликом по виртуальной клавиатуре открывается контекстное меню и подсветка аккорда. Для возврата в режим одной ноты нужно выбрать "Без аккорда" в этом выпадающем меню. + + + + Piano-Roll - %1 Нотный редактор - %1 + + Piano-Roll - no pattern - - - - Quantize - + Пианоролл — нет шаблона PianoView + Base note Опорная нота @@ -5773,20 +7286,24 @@ PM (ФМ) режим значит фазовая модуляция: Осцил Plugin + Plugin not found Модуль не найден + The plugin "%1" wasn't found or could not be loaded! Reason: "%2" Модуль «%1» отсутствует либо не может быть загружен! Причина: «%2» + Error while loading plugin Ошибка загрузки модуля + Failed to load plugin "%1"! Не получилось загрузить модуль «%1»! @@ -5794,25 +7311,30 @@ Reason: "%2" PluginBrowser + + Instrument Plugins + Плагины инструментов + + + Instrument browser Обзор инструментов + Drag an instrument into either the Song-Editor, the Beat+Bassline Editor or into an existing instrument track. Вы можете переносить нужные вам инструменты из этой панели в музыкальный, ритм-бас редактор или в существующую дорожку инструмента. - - Instrument Plugins - Плагины инструментов - PluginFactory + Plugin not found. Плагин не найден + LMMS plugin %1 does not have a plugin descriptor named %2! ЛММС плагин %1 не имеет описания плагина с именем %2! @@ -5820,129 +7342,160 @@ Reason: "%2" ProjectNotes - Edit Actions - Правка - - - &Undo - &U Отменить - - - %1+Z - %1+Z - - - &Redo - &R Повторить - - - %1+Y - %1+Y - - - &Copy - &C Копировать - - - %1+C - %1+C - - - Cu&t - &t Вырезать - - - %1+X - %1+X - - - &Paste - &P Вставить - - - %1+V - %1+V - - - Format Actions - Форматирование - - - &Bold - &b Полужирный - - - %1+B - %1+B - - - &Italic - &i Курсив - - - %1+I - %1+I - - - &Underline - &U Подчеркнутый - - - %1+U - %1+U - - - &Left - &L По левому краю - - - %1+L - %1+L - - - C&enter - По &центру - - - %1+E - - - - &Right - - - - %1+R - - - - &Justify - - - - %1+J - - - - &Color... - - - + Project Notes Показать/скрыть заметки к проекту + Enter project notes here + Напишите заметки, касающиеся проекта здесь + + + + Edit Actions + Правка + + + + &Undo + &U Отменить + + + + %1+Z + %1+Z + + + + &Redo + &R Повторить + + + + %1+Y + %1+Y + + + + &Copy + &C Копировать + + + + %1+C + %1+C + + + + Cu&t + &t Вырезать + + + + %1+X + %1+X + + + + &Paste + &P Вставить + + + + %1+V + %1+V + + + + Format Actions + Форматирование + + + + &Bold + &b Полужирный + + + + %1+B + %1+B + + + + &Italic + &i Курсив + + + + %1+I + %1+I + + + + &Underline + &U Подчеркнутый + + + + %1+U + %1+U + + + + &Left + &L По левому краю + + + + %1+L + %1+L + + + + C&enter + По &центру + + + + %1+E + + + &Right + + + + + %1+R + + + + + &Justify + &Выравнивать + + + + %1+J + + + + + &Color... + &Цвет... + ProjectRenderer + WAV-File (*.wav) Файл WAV (*.wav) + Compressed OGG-File (*.ogg) Сжатый файл OGG (*.ogg) @@ -5951,6 +7504,7 @@ Reason: "%2" + Compressed MP3-File (*.mp3) @@ -5958,57 +7512,89 @@ Reason: "%2" QWidget + + + Name: Название: + + Maker: Создатель: + + Copyright: Правообладатель: + + Requires Real Time: Требуется обработка в реальном времени: + + + + + + Yes Да + + + + + + No Нет + + Real Time Capable: Работа в реальном времени: + + In Place Broken: Вместо сломанного: + + Channels In: Каналы в: + + Channels Out: Каналы из: - File: - Файл: - - + File: %1 Файл: %1 + + + File: + Файл: + RenameDialog + Rename... Переименовать... @@ -6016,34 +7602,42 @@ Reason: "%2" ReverbSCControlDialog + Input Ввод + Input Gain: Входная мощность: + Size Размер + Size: Размер: + Color Цвет + Color: Цвет: + Output Вывод + Output Gain: Выходная мощность: @@ -6051,18 +7645,22 @@ Reason: "%2" ReverbSCControls + Input Gain Входная мощность + Size Размер + Color Цвет + Output Gain Выходная мощность @@ -6070,81 +7668,100 @@ Reason: "%2" SampleBuffer - Open audio file - Открыть звуковой файл - - - Wave-Files (*.wav) - Файлы Wave (*.wav) - - - OGG-Files (*.ogg) - Файлы OGG (*.ogg) - - - DrumSynth-Files (*.ds) - Файлы DrumSynth (*.ds) - - - FLAC-Files (*.flac) - Файлы FLAC (*.flac) - - - SPEEX-Files (*.spx) - Файлы SPEEX (*.spx) - - - VOC-Files (*.voc) - Файлы VOC (*.voc) - - - AIFF-Files (*.aif *.aiff) - Файлы AIFF (*.aif *.aiff) - - - AU-Files (*.au) - Файлы AU (*.au) - - - RAW-Files (*.raw) - Файлы RAW (*.raw) - - - All Audio-Files (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw) - Все аудио файлы (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw) - - + Fail to open file Не удается открыть файл + Audio files are limited to %1 MB in size and %2 minutes of playing time + + + Open audio file + Открыть звуковой файл + + + + All Audio-Files (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw) + Все аудио файлы (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw) + + + + Wave-Files (*.wav) + Файлы Wave (*.wav) + + + + OGG-Files (*.ogg) + Файлы OGG (*.ogg) + + + + DrumSynth-Files (*.ds) + Файлы DrumSynth (*.ds) + + + + FLAC-Files (*.flac) + Файлы FLAC (*.flac) + + + + SPEEX-Files (*.spx) + Файлы SPEEX (*.spx) + + + + VOC-Files (*.voc) + Файлы VOC (*.voc) + + + + AIFF-Files (*.aif *.aiff) + Файлы AIFF (*.aif *.aiff) + + + + AU-Files (*.au) + Файлы AU (*.au) + + + + RAW-Files (*.raw) + Файлы RAW (*.raw) + SampleTCOView + double-click to select sample Выберите запись двойным нажатием мыши + Delete (middle mousebutton) Удалить (средняя кнопка мыши) + Cut Вырезать + Copy Копировать + Paste Вставить + Mute/unmute (<%1> + middle click) Заглушить/включить (<%1> + средняя кнопка мыши) @@ -6152,41 +7769,51 @@ Reason: "%2" SampleTrack - Sample track - Дорожка записи - - + Volume Громкость + Panning Баланс + + + + Sample track + Дорожка записи + SampleTrackView + Track volume Громкость дорожки + Channel volume: Громкость канала: + VOL ГРОМ + Panning Баланс + Panning: Баланс: + PAN БАЛ @@ -6194,496 +7821,658 @@ Reason: "%2" SetupDialog + Setup LMMS Настройка LMMS + + General settings Общие параметры + BUFFER SIZE РАЗМЕР БУФЕРА + + Reset to default-value Восстановить значение по умолчанию + MISC РАЗНОЕ + Enable tooltips Включить подсказки + Show restart warning after changing settings Показывать предупреждение о перезапуске при изменении настроек + + Display volume as dBFS + Отображать громкость в децибелах + + + Compress project files per default По умолчанию сжимать файлы проектов + One instrument track window mode Режим окна одной инструментальной дорожки + HQ-mode for output audio-device Режим высокого качества для устройства вывода звука + Compact track buttons Ужать кнопки дорожки + Sync VST plugins to host playback Синхронизировать VST плагины с хостом воспроизведения + Enable note labels in piano roll Включить обозначение нот в музыкальном редакторе + Enable waveform display by default Включить отображение формы звуков по умолчанию + Keep effects running even without input Продолжать работу эффектов даже без входящего сигнала + Create backup file when saving a project Создать запасной файл при сохранении проекта + + Reopen last project on start + Открыть последний проект на старте + + + + Use built-in NaN handler + + + + + PLUGIN EMBEDDING + + + + + No embedding + Не встраивать + + + + Embed using Qt API + Встроить с использованием QT API + + + + Embed using native Win32 API + Встроить с использованием Win32 API + + + + Embed using XEmbed protocol + Встроить с использованием протокола XEmbed + + + LANGUAGE ЯЗЫК + + Paths Пути + + Directories + Папки + + + LMMS working directory Рабочий каталог LMMS - VST-plugin directory - Каталог модулей VST + + Themes directory + Папка тем + Background artwork Фоновое изображение + + VST-plugin directory + Каталог модулей VST + + + + GIG directory + Папка GIG + + + + SF2 directory + Папка SF2 + + + + LADSPA plugin directories + Папка плагинов LADSPA + + + STK rawwave directory Каталог STK rawwave + Default Soundfont File Основной Soundfont файл + + Performance settings Параметры производительности + + Auto save + Автосохранение + + + + Enable auto-save + Включить автосохранение + + + + Allow auto-save while playing + Разрешить автосохранение во время воспроизведения + + + UI effects vs. performance Визуальные эффекты/производительность + Smooth scroll in Song Editor Плавная прокрутка в музыкальном редакторе + Show playback cursor in AudioFileProcessor Показывать указатель воспроизведения в процессоре аудио файлов (AFP) + + Audio settings Параметры звука + AUDIO INTERFACE ЗВУКОВАЯ СИСТЕМА + + MIDI settings Параметры MIDI + MIDI INTERFACE MIDI СИСТЕМА + OK - ОГА + ОК + Cancel Отменить + Restart LMMS Перезапустить LMMS + Please note that most changes won't take effect until you restart LMMS! Учтите, что большинство настроек не вступят в силу до перезапуска ЛММС! + Frames: %1 Latency: %2 ms Фрагментов: %1 Отклик: %2 + Here you can setup the internal buffer-size used by LMMS. Smaller values result in a lower latency but also may cause unusable sound or bad performance, especially on older computers or systems with a non-realtime kernel. Здесь вы можете настроить размер внутреннего звукового буфера LMMS. Меньшие значения дают меньшее время отклика программы, но повышают потребление ресурсов - это особенно заметно на старых машинах и системах, ядро которых не поддерживает приоритета реального времени. Если наблюдается прерывистый звук, попробуйте увеличить размер буфера. + Choose LMMS working directory Выбор рабочего каталога LMMS - Choose your VST-plugin directory - Выбор своего каталога для модулей VST - - - Choose artwork-theme directory - Выбор каталога с темой оформления для LMMS - - - Choose LADSPA plugin directory - Выбор каталога с модулями LADSPA - - - Choose STK rawwave directory - Выбор каталога STK rawwave - - - Choose default SoundFont - Выбрать главный SoundFont - - - Choose background artwork - Выбрать фоновое изображение - - - Here you can select your preferred audio-interface. Depending on the configuration of your system during compilation time you can choose between ALSA, JACK, OSS and more. Below you see a box which offers controls to setup the selected audio-interface. - Пожалуйста, выберите желаемую звуковую систему. В зависимости от конфигурации во время компилирования программы вы можете использовать ALSA, JACK, OSS и другие. В нижней части окна настройки можно задать специфические параметры выбранной системы. - - - Here you can select your preferred MIDI-interface. Depending on the configuration of your system during compilation time you can choose between ALSA, OSS and more. Below you see a box which offers controls to setup the selected MIDI-interface. - Пожалуйста, выберите интерфейс MIDI. В зависимости от конфигурации во время компилирования программы вы можете использовать ALSA, OSS и другие. В нижней части окна настройки можно задать специфические параметры выбранного интерфейса. - - - Reopen last project on start - Открыть последний проект на старте - - - Directories - Папки - - - Themes directory - Папка тем - - - GIG directory - Папка GIG - - - SF2 directory - Папка SF2 - - - LADSPA plugin directories - Папка плагинов LADSPA - - - Auto save - Автосохранение - - + Choose your GIG directory Выберите вашу папку GIG + Choose your SF2 directory Выберите вашу папку SF2 + + Choose your VST-plugin directory + Выбор своего каталога для модулей VST + + + + Choose artwork-theme directory + Выбор каталога с темой оформления для LMMS + + + + Choose LADSPA plugin directory + Выбор каталога с модулями LADSPA + + + + Choose STK rawwave directory + Выбор каталога STK rawwave + + + + Choose default SoundFont + Выбрать главный SoundFont + + + + Choose background artwork + Выбрать фоновое изображение + + + minutes Минуты + minute Минута - Display volume as dBFS - Отображать громкость в децибелах - - - Enable auto-save - Включить автосохранение - - - Allow auto-save while playing - Разрешить автосохранение во время воспроизведения - - + Disabled Отключено + Auto-save interval: %1 - + Интервал автосорхранения: %1 + Set the time between automatic backup to %1. Remember to also save your project manually. You can choose to disable saving while playing, something some older systems find difficult. Установить время между автоматическим бэкапом на %1. Не забывайте сохранять проект вручную. + + + Here you can select your preferred audio-interface. Depending on the configuration of your system during compilation time you can choose between ALSA, JACK, OSS and more. Below you see a box which offers controls to setup the selected audio-interface. + Пожалуйста, выберите желаемую звуковую систему. В зависимости от конфигурации во время компилирования программы вы можете использовать ALSA, JACK, OSS и другие. В нижней части окна настройки можно задать специфические параметры выбранной системы. + + + + Here you can select your preferred MIDI-interface. Depending on the configuration of your system during compilation time you can choose between ALSA, OSS and more. Below you see a box which offers controls to setup the selected MIDI-interface. + Пожалуйста, выберите интерфейс MIDI. В зависимости от конфигурации во время компилирования программы вы можете использовать ALSA, OSS и другие. В нижней части окна настройки можно задать специфические параметры выбранного интерфейса. + Song + Tempo Темп + Master volume Основная громкость + Master pitch Основная тональность + + LMMS Error report + Отчет об ошибке LMMS + + + Project saved Проект сохранён + The project %1 is now saved. Проект %1 сохранён. + Project NOT saved. Проект НЕ СОХРАНЁН. + The project %1 was not saved! Проект %1 не сохранён! + Import file Импорт файла + MIDI sequences MiDi последовательности + Hydrogen projects Hydrogen проекты + All file types Все типы файлов + + Empty project Пустой проект + + This project is empty so exporting makes no sense. Please put some items into Song Editor first! Проект ничего не содержит, так что и экспортировать нечего. Сначала добавьте хотя бы одну дорожку в музыкальном редакторе! + Select directory for writing exported tracks... Выберите папку для записи экспортированных дорожек... + + untitled Неназванное + + Select file for project-export... Выбор файла для экспорта проекта... - The following errors occured while loading: - Следующие ошибки возникли при загрузке: - - - MIDI File (*.mid) - - - - LMMS Error report - - - + Save project Сохранить проект + + + MIDI File (*.mid) + MIDI-файл (*.mid) + + + + The following errors occured while loading: + Следующие ошибки возникли при загрузке: + SongEditor + Could not open file Не могу открыть файл - Could not write file - Не могу записать файл - - + Could not open file %1. You probably have no permissions to read this file. Please make sure to have at least read permissions to the file and try again. Невозможно открыть файл %1, вероятно, нет разрешений на его чтение. Пж. убедитесь, что есть по крайней мере права на чтение этого файла и попробуйте ещё раз. - Error in file - Ошибка в файле - - - The file %1 seems to contain errors and therefore can't be loaded. - Файл %1 возможно содержит ошибки из-за которых не может загрузиться. - - - Tempo - Темп - - - TEMPO/BPM - ТЕМП/BPM - - - tempo of song - Темп музыки - - - The tempo of a song is specified in beats per minute (BPM). If you want to change the tempo of your song, change this value. Every measure has four beats, so the tempo in BPM specifies, how many measures / 4 should be played within a minute (or how many measures should be played within four minutes). - Это значение задаёт темп музыки в ударах в минуту (англ. аббр. BPM). На каждый такт приходится четыре удара, так что темп в ударах в минуту фактически указывает, сколько четвертей такта проигрывается за минуту (или, что то же, количество тактов, проигрываемых за четыре минуты). - - - High quality mode - Высокое качество - - - Master volume - Основная громкость - - - master volume - основная громкость - - - Master pitch - Основная тональность - - - master pitch - основная тональность - - - Value: %1% - Значение: %1% - - - Value: %1 semitones - Значение: %1 полутон(а/ов) + + Could not write file + Не могу записать файл + Could not open %1 for writing. You probably are not permitted to write to this file. Please make sure you have write-access to the file and try again. Невозможно открыть %1 для записи, возможно, нет разрешений на запись в этот файл, пж. удостоверьтесь, что есть доступ к этому файлу и попробуйте снова. - template - + + Error in file + Ошибка в файле - project - + + The file %1 seems to contain errors and therefore can't be loaded. + Файл %1 возможно содержит ошибки из-за которых не может загрузиться. + Version difference Версия отличается + This %1 was created with LMMS %2. - + %1 был создан в LMMS %2. + + + + template + шаблон + + + + project + проект + + + + Tempo + Темп + + + + TEMPO/BPM + ТЕМП/BPM + + + + tempo of song + Темп музыки + + + + The tempo of a song is specified in beats per minute (BPM). If you want to change the tempo of your song, change this value. Every measure has four beats, so the tempo in BPM specifies, how many measures / 4 should be played within a minute (or how many measures should be played within four minutes). + Это значение задаёт темп музыки в ударах в минуту (англ. аббр. BPM). На каждый такт приходится четыре удара, так что темп в ударах в минуту фактически указывает, сколько четвертей такта проигрывается за минуту (или, что то же, количество тактов, проигрываемых за четыре минуты). + + + + High quality mode + Высокое качество + + + + + Master volume + Основная громкость + + + + master volume + основная громкость + + + + + Master pitch + Основная тональность + + + + master pitch + основная тональность + + + + Value: %1% + Значение: %1% + + + + Value: %1 semitones + Значение: %1 полутон(а/ов) SongEditorWindow + Song-Editor Музыкальный редактор + Play song (Space) Начать воспроизведение (Пробел) + Record samples from Audio-device Записать сэмпл со звукового устройства + Record samples from Audio-device while playing song or BB track Записать сэмпл с аудио-устройства во время воспроизведения в музыкальном или ритм/бас редакторе + Stop song (Space) Остановить воспроизведение (Пробел) - Add beat/bassline - Добавить ритм/бас - - - Add sample-track - Добавить дорожку записи - - - Add automation-track - Добавить дорожку автоматизации - - - Draw mode - Режим рисования - - - Edit mode (select and move) - Правка (выделение/перемещение) - - + Click here, if you want to play your whole song. Playing will be started at the song-position-marker (green). You can also move it while playing. Нажмите, чтобы прослушать созданную мелодию. Воспроизведение начнётся с позиции курсора (зелёный треугольник); вы можете двигать его во время проигрывания. + Click here, if you want to stop playing of your song. The song-position-marker will be set to the start of your song. Нажмите сюда, если вы хотите остановить воспроизведение мелодии. Курсор при этом будет установлен на начало композиции. + Track actions - + Действия трека + + Add beat/bassline + Добавить ритм/бас + + + + Add sample-track + Добавить дорожку записи + + + + Add automation-track + Добавить дорожку автоматизации + + + Edit actions Правка: + + Draw mode + Режим рисования + + + + Edit mode (select and move) + Правка (выделение/перемещение) + + + Timeline controls Управление временем + Zoom controls Приблизить управление @@ -6691,10 +8480,12 @@ Remember to also save your project manually. You can choose to disable saving wh SpectrumAnalyzerControlDialog + Linear spectrum Линейный спектр + Linear Y axis Линейная ось ординат (Y) @@ -6702,14 +8493,17 @@ Remember to also save your project manually. You can choose to disable saving wh SpectrumAnalyzerControls + Linear spectrum Линейный спектр + Linear Y axis Линейная ось ординат (Y) + Channel mode Режим канала @@ -6717,14 +8511,17 @@ Remember to also save your project manually. You can choose to disable saving wh SubWindow + Close Закрыть + Maximize Развернуть + Restore Восстановить @@ -6732,6 +8529,8 @@ Remember to also save your project manually. You can choose to disable saving wh TabWidget + + Settings for %1 Настройки для %1 @@ -6739,74 +8538,93 @@ Remember to also save your project manually. You can choose to disable saving wh TempoSyncKnob + + Tempo Sync Синхронизация темпа + No Sync Синхронизации нет + Eight beats Восемь ударов (две ноты) + Whole note Целая нота + Half note Полунота + Quarter note Четверть ноты + 8th note Восьмая ноты + 16th note 1/16 ноты + 32nd note 1/32 ноты + Custom... Своя... + Custom Своя + Synced to Eight Beats Синхро по 8 ударам + Synced to Whole Note Синхро по целой ноте + Synced to Half Note Синхро по половине ноты + Synced to Quarter Note Синхро по четверти ноты + Synced to 8th Note Синхро по 1/8 ноты + Synced to 16th Note Синхро по 1/16 ноты + Synced to 32nd Note Синхро по 1/32 ноты @@ -6814,65 +8632,81 @@ Remember to also save your project manually. You can choose to disable saving wh TimeDisplayWidget + click to change time units нажми для изменения единиц времени + MIN - + МИН + SEC - + СЕК + MSEC - + мСЕК + BAR - + ДЕЛЕНИЕ + BEAT - + БИТ + TICK - + ТИК TimeLineWidget + Enable/disable auto-scrolling Вкл/выкл автопрокрутку + Enable/disable loop-points Вкл/выкл точки петли + After stopping go back to begin После остановки переходить к началу + After stopping go back to position at which playing was started После остановки переходить к месту, с которого началось воспроизведение + After stopping keep position Оставаться на месте остановки + + Hint Подсказка + Press <%1> to disable magnetic loop points. Нажмите <%1>, чтобы убрать прилипание точек петли. + Hold <Shift> to move the begin loop point; Press <%1> to disable magnetic loop points. Зажмите <Shift> чтобы сдвинуть начало точек петли; Нажмите <%1>, чтобы убрать прилипание точек петли. @@ -6880,10 +8714,12 @@ Remember to also save your project manually. You can choose to disable saving wh Track + Mute Тихо + Solo Соло @@ -6891,49 +8727,71 @@ Remember to also save your project manually. You can choose to disable saving wh TrackContainer + Couldn't import file Не могу импортировать файл + Couldn't find a filter for importing file %1. You should convert this file into a format supported by LMMS using another software. Не могу найти фильтр для импорта файла %1. Для подключения этого файла преобразуйте его в формат, поддерживаемый LMMS. + Couldn't open file Не могу открыть файл + Couldn't open file %1 for reading. Please make sure you have read-permission to the file and the directory containing the file and try again! Не могу открыть файл %1 для записи. Проверьте, обладаете ли вы правами на запись в выбранный файл и содержащий его каталог и попробуйте снова! + Loading project... Чтение проекта... + + Cancel Отменить + + Please wait... Подождите, пожалуйста... - Importing MIDI-file... - Импортирую файл MIDI... + + Loading cancelled + Загрузка отменена. + + Project loading was cancelled. + Загрузка проекта была отменена. + + + Loading Track %1 (%2/Total %3) + + + Importing MIDI-file... + Импортирую файл MIDI... + TrackContentObject + Mute Тихо @@ -6941,46 +8799,59 @@ Please make sure you have read-permission to the file and the directory containi TrackContentObjectView + Current position Текущая позиция + + Hint Подсказка + Press <%1> and drag to make a copy. Нажмите <%1> и тащите мышью, чтобы создать копию. + Current length Текущая длительность + Press <%1> for free resizing. Для свободного изменения размера нажмите <%1>. + + %1:%2 (%3:%4 to %5:%6) %1:%2 (от %3:%4 до %5:%6) + Delete (middle mousebutton) Удалить (средняя кнопка мыши) + Cut Вырезать + Copy Копировать + Paste Вставить + Mute/unmute (<%1> + middle click) Тихо/громко (<%1> + middle click) @@ -6988,193 +8859,243 @@ Please make sure you have read-permission to the file and the directory containi TrackOperationsWidget + Press <%1> while clicking on move-grip to begin a new drag'n'drop-action. Зажмите <Сtrl> и нажимайте мышь во время движения, чтобы начать новую переброску. + Actions for this track Действия для этой дорожки + Mute Тихо + + Solo Соло + Mute this track Заглушить эту дорожку + Clone this track Клонировать дорожку + Remove this track Удалить дорожку + Clear this track Очистить эту дорожку + FX %1: %2 ЭФ %1: %2 + + Assign to new FX Channel + Назначить на другой канал ЭФфектов + + + Turn all recording on Включить всё на запись + Turn all recording off Выключить всю запись - - Assign to new FX Channel - Назначить на другой канал ЭФфектов - TripleOscillatorView + Use phase modulation for modulating oscillator 1 with oscillator 2 Модулировать фазу осциллятора 2 сигналом с 1 + Use amplitude modulation for modulating oscillator 1 with oscillator 2 Модулировать амплитуду осциллятора 2 сигналом с первого + Mix output of oscillator 1 & 2 Смешать выводы 1 и 2 осцилляторов + Synchronize oscillator 1 with oscillator 2 Синхронизировать первый осциллятор по второму + Use frequency modulation for modulating oscillator 1 with oscillator 2 Модулировать частоту осциллятора 2 сигналом с 1 + Use phase modulation for modulating oscillator 2 with oscillator 3 Модулировать фазу осциллятора 3 сигналом с 2 + Use amplitude modulation for modulating oscillator 2 with oscillator 3 Модулировать амплитуду осциллятора 3 сигналом с 2 + Mix output of oscillator 2 & 3 Совместить вывод осцилляторов 2 и 3 + Synchronize oscillator 2 with oscillator 3 Синхронизировать осциллятор 2 и 3 + Use frequency modulation for modulating oscillator 2 with oscillator 3 Модулировать частоту осциллятора 3 сигналом со 2 + Osc %1 volume: Громкость осциллятора %1: + With this knob you can set the volume of oscillator %1. When setting a value of 0 the oscillator is turned off. Otherwise you can hear the oscillator as loud as you set it here. Эта ручка устанавливает громкость осциллятора %1. Если 0, то осциллятор выключается, иначе будет слышно настолько громко , как тут установлено. + Osc %1 panning: Баланс для осциллятора %1: + With this knob you can set the panning of the oscillator %1. A value of -100 means 100% left and a value of 100 moves oscillator-output right. Регулятор стереобаланса осциллятора %1. Величина -100 обозначает, что 100% сигнала идёт в левый канал, а 100 - в правый. + Osc %1 coarse detuning: Грубая подстройка осциллятора %1: + semitones полутон[а,ов] + With this knob you can set the coarse detuning of oscillator %1. You can detune the oscillator 24 semitones (2 octaves) up and down. This is useful for creating sounds with a chord. Грубая регулировка подстройки осциллятора %1. Возможна подстройка до 24 полутонов (до 2 октавы) вверх и вниз. Полезно для создания аккордов. + Osc %1 fine detuning left: Точная подстройка левого канала осциллятора %1: + + cents Проценты + With this knob you can set the fine detuning of oscillator %1 for the left channel. The fine-detuning is ranged between -100 cents and +100 cents. This is useful for creating "fat" sounds. Эта ручка устанавливает точную подстройку для левого канала осциллятора %1. Подстройка задаётся в диапазоне от -100 сотых до +100 сотых. Это полезно для создания "сочных" звуков. + Osc %1 fine detuning right: Точная подстройка правого канала осциллятора %1: + With this knob you can set the fine detuning of oscillator %1 for the right channel. The fine-detuning is ranged between -100 cents and +100 cents. This is useful for creating "fat" sounds. Эта ручка устанавливает точную подстройку для правого канала осциллятора %1. Подстройка задаётся в диапазоне от -100 сотых до +100 сотых. Это полезно для создания "сочных" звуков. + Osc %1 phase-offset: Сдвиг фазы осциллятора %1: + + degrees градусы + With this knob you can set the phase-offset of oscillator %1. That means you can move the point within an oscillation where the oscillator begins to oscillate. For example if you have a sine-wave and have a phase-offset of 180 degrees the wave will first go down. It's the same with a square-wave. Эта ручка устанавливает начальную фазу осциллятора %1, т. е. точку, с которой осциллятор начинает вырабатывать сигнал. Например, если вы задали синусоидальную форму сигнала и начальную фазу 180º, волна сначала пойдёт вниз, а не вверх. То же для меандра (сигнала прямоугольной формы). + Osc %1 stereo phase-detuning: Подстройка стерео фазы осциллятора %1: + With this knob you can set the stereo phase-detuning of oscillator %1. The stereo phase-detuning specifies the size of the difference between the phase-offset of left and right channel. This is very good for creating wide stereo sounds. Эта ручка устанавливает фазовую подстройку осциллятора %1 между каналами, то есть разность фаз между левым и правым каналами. Это удобно для создания расширения стереоэффектов. + Use a sine-wave for current oscillator. - Использовать гармонический (синусоидальный) сигнал для этого осциллятора. + Генерировать гармонический (синусоидальный) сигнал. + Use a triangle-wave for current oscillator. - Использовать треугольный сигнал для этого осциллятора. + Генерировать треугольный сигнал. + Use a saw-wave for current oscillator. - Использовать зигзагообразный сигнал для этого осциллятора. + Генерировать зигзагообразный сигнал. + Use a square-wave for current oscillator. - Использовать квадратный сигнал (меандр) для этого осциллятора. + Генерировать квадрат (меандр). + Use a moog-like saw-wave for current oscillator. Использовать муг-зигзаг для этого осциллятора. + Use an exponential wave for current oscillator. Использовать экспоненциальный сигнал для этого осциллятора. + Use white-noise for current oscillator. - Использовать белый шум для этого осциллятора. + Генерировать белый шум. + Use a user-defined waveform for current oscillator. Задать форму сигнала. @@ -7182,105 +9103,131 @@ Please make sure you have read-permission to the file and the directory containi VersionedSaveDialog + Increment version number Увеличивающийся номер версии + Decrement version number Понижающийся номер версии + already exists. Do you want to replace it? - + уже существует. Хотите перезаписать? VestigeInstrumentView + Open other VST-plugin Открыть другой VST плагин + Click here, if you want to open another VST-plugin. After clicking on this button, a file-open-dialog appears and you can select your file. Открыть другой модуль VST. После нажатия на кнопку появится стандартный диалог выбора файла, где вы сможете выбрать нужный модуль. - Show/hide GUI - Показать/скрыть интерфейс - - - Click here to show or hide the graphical user interface (GUI) of your VST-plugin. - Скрывает/показывает графический пользовательский интерфейс (GUI) выбранного модуля VST. - - - Turn off all notes - Выключить все ноты - - - Open VST-plugin - Открыть модуль VST - - - DLL-files (*.dll) - Бибилиотеки DLL (*.dll) - - - EXE-files (*.exe) - Программы EXE (*.exe) - - - No VST-plugin loaded - Модуль VST не загружен - - + Control VST-plugin from LMMS host - Управление VST плагином через LMMS + Управление VST плагином через LMMS хост + Click here, if you want to control VST-plugin from host. - Нажмите здесь для контроля VST плагина через хост. + Нажмите здесь, для контроля VST плагином через хост. + Open VST-plugin preset - Открыть предустановку VST модуля + Открыть предустановку VST плагина + Click here, if you want to open another *.fxp, *.fxb VST-plugin preset. Открыть другую .fxp . fxb предустановку VST. + Previous (-) Предыдущий <-> + + Click here, if you want to switch to another VST-plugin preset program. - Нажмите здесь для переключения на другую предустановку программы VST плагина. + Переключение на другую предустановку программы VST плагина. + Save preset Сохранить предустановку + Click here, if you want to save current VST-plugin preset program. Сохранить текущую предустановку программы VST плагина. + Next (+) Следующий <+> + Click here to select presets that are currently loaded in VST. Выбор из уже загруженных в VST предустановок. + + Show/hide GUI + Показать/скрыть интерфейс + + + + Click here to show or hide the graphical user interface (GUI) of your VST-plugin. + Скрывает/показывает графический пользовательский интерфейс (GUI) выбранного модуля VST. + + + + Turn off all notes + Выключить все ноты + + + + Open VST-plugin + Открыть модуль VST + + + + DLL-files (*.dll) + Бибилиотеки DLL (*.dll) + + + + EXE-files (*.exe) + Программы EXE (*.exe) + + + + No VST-plugin loaded + Модуль VST не загружен + + + Preset Предустановка + by от + - VST plugin control - управление VST плагином @@ -7288,10 +9235,12 @@ Please make sure you have read-permission to the file and the directory containi VisualizationWidget + click to enable/disable visualization of master-output Нажмите, чтобы включить/выключить визуализацию главного вывода + Click to enable Нажать для включения @@ -7299,54 +9248,69 @@ Please make sure you have read-permission to the file and the directory containi VstEffectControlDialog + Show/hide Показать/Скрыть + Control VST-plugin from LMMS host Управление VST плагином через LMMS хост + Click here, if you want to control VST-plugin from host. Нажмите здесь, для контроля VST плагином через хост. + Open VST-plugin preset Открыть предустановку VST плагина + Click here, if you want to open another *.fxp, *.fxb VST-plugin preset. Открыть другую .fxp . fxb предустановку VST. + Previous (-) Предыдущий <-> + + Click here, if you want to switch to another VST-plugin preset program. Переключение на другую предустановку программы VST плагина. + Next (+) Следующий <+> + Click here to select presets that are currently loaded in VST. Выбор из уже загруженных в VST предустановок. + Save preset Сохранить настройку + Click here, if you want to save current VST-plugin preset program. Сохранить текущую предустановку программы VST плагина. + + Effect by: Эффекты по: + &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /> @@ -7354,387 +9318,509 @@ Please make sure you have read-permission to the file and the directory containi VstPlugin - Loading plugin - Загрузка модуля + + + The VST plugin %1 could not be loaded. + VST плагин %1 не может быть загружен. + Open Preset Открыть предустановку + + Vst Plugin Preset (*.fxp *.fxb) Предустановка VST плагина (*.fxp *.fxb) + : default : основные + " " + ' ' + Save Preset Сохранить предустановку + .fxp .fxp + .FXP .FXP + .FXB .FXB + .fxb .fxb - Please wait while loading VST plugin... - Пожалуйста, подождите пока грузится VST плагин... + + Loading plugin + Загрузка модуля - The VST plugin %1 could not be loaded. - VST плагин %1 не может быть загружен. + + Please wait while loading VST plugin... + Пожалуйста, подождите пока грузится VST плагин... WatsynInstrument + Volume A1 - + Громкость А1 + Volume A2 - + Громкость А2 + Volume B1 - + Громкость B1 + Volume B2 - + Громкость B2 + Panning A1 + Panning A2 + Panning B1 + Panning B2 + Freq. multiplier A1 - + Множитель частоты А1 + Freq. multiplier A2 - + Множитель частоты А2 + Freq. multiplier B1 - + Множитель частоты B1 + Freq. multiplier B2 - + Множитель частоты B2 + Left detune A1 + Left detune A2 + Left detune B1 + Left detune B2 + Right detune A1 + Right detune A2 + Right detune B1 + Right detune B2 + A-B Mix + A-B Mix envelope amount + A-B Mix envelope attack + A-B Mix envelope hold + A-B Mix envelope decay + A1-B2 Crosstalk + A2-A1 modulation + B2-B1 modulation + Selected graph - + Выбранный график WatsynView - Select oscillator A1 - - - - Select oscillator A2 - - - - Select oscillator B1 - - - - Select oscillator B2 - - - - Mix output of A2 to A1 - - - - Modulate amplitude of A1 with output of A2 - Модулировать амплитуду A1 сигналом с A2 - - - Ring-modulate A1 and A2 - Кольцевая модуляция А1 и А2 - - - Modulate phase of A1 with output of A2 - Модулировать фазу A1 сигналом с A2 - - - Mix output of B2 to B1 - - - - Modulate amplitude of B1 with output of B2 - Модулировать амплитуду B1 сигналом с B2 - - - Ring-modulate B1 and B2 - Кольцевая модуляция B1 и B2 - - - Modulate phase of B1 with output of B2 - Модулировать фазу B1 сигналом с B2 - - - Draw your own waveform here by dragging your mouse on this graph. - Здесь вы можете рисовать собственный сигнал передвигая зажатой мышью по этому графу. - - - Load waveform - - - - Click to load a waveform from a sample file - Кликнуть для загрузки формы звука из файла с образцом - - - Phase left - Фаза слева - - - Click to shift phase by -15 degrees - - - - Phase right - Фаза справа - - - Click to shift phase by +15 degrees - - - - Normalize - Нормализовать - - - Click to normalize - - - - Invert - - - - Click to invert - - - - Smooth - Сгладить - - - Click to smooth - - - - Sine wave - Синусоида - - - Click for sine wave - - - - Triangle wave - Треугольная волна - - - Click for triangle wave - - - - Click for saw wave - - - - Square wave - Квадрат - - - Click for square wave - - - + + + + Volume Громкость + + + + Panning Баланс + + + + Freq. multiplier - + Множитель частоты + + + + Left detune + + + + + + + + cents + + + + Right detune + A-B Mix + Mix envelope amount + Mix envelope attack + Mix envelope hold + Mix envelope decay + Crosstalk + + + Select oscillator A1 + + + + + Select oscillator A2 + + + + + Select oscillator B1 + + + + + Select oscillator B2 + + + + + Mix output of A2 to A1 + + + + + Modulate amplitude of A1 with output of A2 + Модулировать амплитуду A1 сигналом с A2 + + + + Ring-modulate A1 and A2 + Кольцевая модуляция А1 и А2 + + + + Modulate phase of A1 with output of A2 + Модулировать фазу A1 сигналом с A2 + + + + Mix output of B2 to B1 + + + + + Modulate amplitude of B1 with output of B2 + Модулировать амплитуду B1 сигналом с B2 + + + + Ring-modulate B1 and B2 + Кольцевая модуляция B1 и B2 + + + + Modulate phase of B1 with output of B2 + Модулировать фазу B1 сигналом с B2 + + + + + + + Draw your own waveform here by dragging your mouse on this graph. + Здесь вы можете рисовать собственный сигнал передвигая зажатой мышью по этому графу. + + + + Load waveform + + + + + Click to load a waveform from a sample file + Кликнуть для загрузки формы звука из файла с образцом + + + + Phase left + Фаза слева + + + + Click to shift phase by -15 degrees + + + + + Phase right + Фаза справа + + + + Click to shift phase by +15 degrees + + + + + Normalize + Нормализовать + + + + Click to normalize + + + + + Invert + Инвертировать + + + + Click to invert + + + + + Smooth + Сгладить + + + + Click to smooth + + + + + Sine wave + Синусоида + + + + Click for sine wave + + + + + + Triangle wave + Треугольная волна + + + + Click for triangle wave + + + + + Click for saw wave + + + + + Square wave + Квадрат + + + + Click for square wave + + ZynAddSubFxInstrument + Portamento Портаменто + Filter Frequency Фильтр Частот + Filter Resonance Фильтр резонанса + Bandwidth Ширина полосы + FM Gain Усил FM + Resonance Center Frequency Частоты центра резонанса + Resonance Bandwidth Ширина полосы резонанса + Forward MIDI Control Change Events Переслать изменение событий MiDi управления @@ -7742,121 +9828,150 @@ Please make sure you have read-permission to the file and the directory containi ZynAddSubFxView - Show GUI - Показать интерфейс - - - Click here to show or hide the graphical user interface (GUI) of ZynAddSubFX. - Скрыть или показать графический интерфейс ZynAddSubFX. - - + Portamento: Портаменто: + PORT PORT + Filter Frequency: Фильтр частот: + FREQ FREQ + Filter Resonance: Фильтр резонанса: + RES RES + Bandwidth: Полоса пропускания: + BW BW + FM Gain: Усиление частоты модуляции (FM): + FM GAIN FM GAIN + Resonance center frequency: Частоты центра резонанса: + RES CF RES CF + Resonance bandwidth: Ширина полосы резонанса: + RES BW RES BW + Forward MIDI Control Changes Переслать изменение событий MiDi управления + + + Show GUI + Показать интерфейс + + + + Click here to show or hide the graphical user interface (GUI) of ZynAddSubFX. + Скрыть или показать графический интерфейс ZynAddSubFX. + audioFileProcessor + Amplify Усиление + Start of sample Начало записи + End of sample Конец записи - Reverse sample - Перевернуть запись - - - Stutter - Запинание - - + Loopback point Точка петли + + Reverse sample + Перевернуть запись + + + Loop mode Режим повтора + + Stutter + Запинание + + + Interpolation mode Режим интерполяции + None Нет + Linear - + Линеарный + Sinc + Sample not found: %1 Сэмпл не найден: %1 @@ -7864,6 +9979,7 @@ Please make sure you have read-permission to the file and the directory containi bitInvader + Samplelength Длительность @@ -7871,165 +9987,205 @@ Please make sure you have read-permission to the file and the directory containi bitInvaderView + Sample Length Длительность записи - Sine wave - Синусоида - - - Triangle wave - Треугольник - - - Saw wave - Зигзаг - - - Square wave - Квадрат (Меандр) - - - White noise wave - Белый шум - - - User defined wave - Пользовательская - - - Smooth - Сгладить - - - Click here to smooth waveform. - Щёлкните чтобы сгладить форму сигнала. - - - Interpolation - Интерполяция - - - Normalize - Нормализовать - - + Draw your own waveform here by dragging your mouse on this graph. Здесь вы можете рисовать собственный сигнал. + + Sine wave + Синусоида + + + Click for a sine-wave. Сгенерировать гармонический (синусоидальный) сигнал. + + Triangle wave + Треугольник + + + Click here for a triangle-wave. Сгенерировать треугольный сигнал. + + Saw wave + Зигзаг + + + Click here for a saw-wave. - Сгенерировать загзагообразный сигнал. + Сгенерировать зигзаг. + + Square wave + Квадрат (Меандр) + + + Click here for a square-wave. - Сгенерировать квадратную волну (меандр). + Сгенерировать квадрат. + + White noise wave + Белый шум + + + Click here for white-noise. Сгенерировать белый шум. + + User defined wave + Пользовательская + + + Click here for a user-defined shape. Задать форму сигнала вручную. + + + Smooth + Сгладить + + + + Click here to smooth waveform. + Щёлкните чтобы сгладить форму сигнала. + + + + Interpolation + Интерполяция + + + + Normalize + Нормализовать + dynProcControlDialog + INPUT ВХОД + Input gain: Входная мощность: + OUTPUT Выход + Output gain: Выходная мощность: + ATTACK АТАКА + Peak attack time: Время пиковой атаки: + RELEASE ОТПУСК + Peak release time: Время отпуска пика: + Reset waveform Сбросить волну + Click here to reset the wavegraph back to default - Нажмите здесь, чтобы скинуть граф волны обратно по умолчанию + Сбросить граф волны обратно по умолчанию + Smooth waveform Сгладить волну + Click here to apply smoothing to wavegraph - Нажмите здесь, чтобы применить сглаживание графа волны + Применить сглаживание к графу волны + Increase wavegraph amplitude by 1dB - Повысить амплитуду графа волны на 1дБ + Повысить амплитуду графа волны на 1 дБ + Click here to increase wavegraph amplitude by 1dB - Нажмите здесь, чтобы увеличить амплитуду графа волны на 1дБ + Нажмите здесь, чтобы повысить амплитуду графа волны на 1 дБ + Decrease wavegraph amplitude by 1dB - Снизить амплитуду графа волны на 1дБ + Снизить амплитуду графа волны на 1 дБ + Click here to decrease wavegraph amplitude by 1dB - Нажмите здесь, чтобы снизить амплитуду графа волны на 1дБ + Снизить амплитуду графа волны на 1 дБ + Stereomode Maximum Стереорежим Максимум + Process based on the maximum of both stereo channels Процесс основанный на максимуме от обоих каналов + Stereomode Average Стереорежим Средний + Process based on the average of both stereo channels Процесс основанный на средней обоих каналов + Stereomode Unlinked Стереорежим Отдельный + Process each stereo channel independently Обрабатывает каждый стерео канал независимо @@ -8037,22 +10193,27 @@ Please make sure you have read-permission to the file and the directory containi dynProcControls + Input gain Входная мощность + Output gain Выходная мощность + Attack time Время атаки + Release time Время отпуска + Stereo mode Режим стерео @@ -8187,10 +10348,12 @@ Please make sure you have read-permission to the file and the directory containi fxLineLcdSpinBox + Assign to: - + Назначить на: + New FX Channel Новый канал ЭФ @@ -8198,6 +10361,7 @@ Please make sure you have read-permission to the file and the directory containi graphModel + Graph Граф @@ -8205,93 +10369,115 @@ Please make sure you have read-permission to the file and the directory containi kickerInstrument + Start frequency Начальная частота + End frequency Конечная частота - Gain - Усиление - - + Length Длина + Distortion Start Начало искажения + Distortion End Конец искажения - Envelope Slope - + + Gain + Усиление + + Envelope Slope + Сглаживание кривой + + + Noise Шум + Click - + Клик + Frequency Slope - + Сглаживание частоты + Start from note + End to note - + Конец для ноты kickerInstrumentView + Start frequency: Начальная частота: + End frequency: Конечная частота: - Gain: - Усиление: - - + Frequency Slope: + + Gain: + Усиление: + + + Envelope Length: + Envelope Slope: + Click: - + Клик: + Noise: Шум: + Distortion Start: + Distortion End: @@ -8299,26 +10485,37 @@ Please make sure you have read-permission to the file and the directory containi ladspaBrowserView + + Available Effects Доступные эффекты + + Unavailable Effects Недоступные эффекты + + Instruments Инструменты + + Analysis Tools Анализаторы + + Don't know Неизвестные + This dialog displays information on all of the LADSPA plugins LMMS was able to locate. The plugins are divided into five categories based upon an interpretation of the port types and names. Available Effects are those that can be used by LMMS. In order for LMMS to be able to use an effect, it must, first and foremost, be an effect, which is to say, it has to have both input channels and output channels. LMMS identifies an input channel as an audio rate port containing 'in' in the name. Output channels are identified by the letters 'out'. Furthermore, the effect must have the same number of inputs and outputs and be real time capable. @@ -8347,6 +10544,7 @@ Double clicking any of the plugins will bring up information on the ports. + Type: Тип: @@ -8354,10 +10552,12 @@ Double clicking any of the plugins will bring up information on the ports. ladspaDescription + Plugins Модули + Description Описание @@ -8365,66 +10565,83 @@ Double clicking any of the plugins will bring up information on the ports. ladspaPortDialog + Ports Порты + Name Название + Rate Частота выборки + Direction Направление + Type Тип + Min < Default < Max Меньше < Стандарт < Больше + Logarithmic Логарифмический + SR Dependent Зависимость от SR + Audio Аудио + Control Управление + Input Ввод + Output Вывод + Toggled Включено + Integer Целое + Float Дробное + + Yes Да @@ -8432,46 +10649,57 @@ Double clicking any of the plugins will bring up information on the ports. lb302Synth + VCF Cutoff Frequency Частота среза VCF + VCF Resonance Усиление VCF + VCF Envelope Mod Модуляция огибающей VCF + VCF Envelope Decay Спад огибающей VCF + Distortion Искажение + Waveform Форма сигнала + Slide Decay Сдвиг затухания + Slide Сдвиг + Accent Акцент + Dead Глухо + 24dB/oct Filter 24дБ/окт фильтр @@ -8479,122 +10707,153 @@ Double clicking any of the plugins will bring up information on the ports. lb302SynthView + Cutoff Freq: Частота среза: + Resonance: Отзвук: + Env Mod: Мод Огиб: + Decay: - Спад: + Затухание: + 303-es-que, 24dB/octave, 3 pole filter 303-ий, 24дБ/октаву, 3-польный фильтр + Slide Decay: - Сдвиг спада: + Сдвиг затухания: + DIST: ИСК: + Saw wave Зигзаг + Click here for a saw-wave. Сгенерировать зигзаг. + Triangle wave Треугольная волна + Click here for a triangle-wave. Сгенерировать треугольный сигнал. + Square wave Квадрат + Click here for a square-wave. Сгенерировать квадрат. + Rounded square wave Волна скругленного квадрата + Click here for a square-wave with a rounded end. Создать квадратную волну закруглённую в конце. + Moog wave Муг волна + Click here for a moog-like wave. Сгенерировать волну похожую на муг. + Sine wave Синусоида + Click for a sine-wave. Сгенерировать гармонический (синусоидальный) сигнал. + + White noise wave Белый шум + Click here for an exponential wave. Генерировать экспоненциальный сигнал. + Click here for white-noise. Сгенерировать белый шум. + Bandlimited saw wave + Click here for bandlimited saw wave. Нажать здесь для пилообразной волны с ограниченной полосой. + Bandlimited square wave + Click here for bandlimited square wave. Нажать здесь для квадратной волны с ограниченной полосой. + Bandlimited triangle wave - + Ограниченная треугольная волна + Click here for bandlimited triangle wave. Нажать здесь для треуголной волны с ограниченной полосой. + Bandlimited moog saw wave - + Пружинная волна с ограниченной полосой + Click here for bandlimited moog saw wave. Нажать здесь для пилообразной муг (moog) волны с ограниченной полосой. @@ -8602,118 +10861,147 @@ Double clicking any of the plugins will bring up information on the ports. malletsInstrument + Hardness Жёсткость + Position Положение + Vibrato Gain Усиление вибрато + Vibrato Freq Частота вибрато + Stick Mix Сведение ручек + Modulator Модулятор + Crossfade Переход + LFO Speed Скорость LFO + LFO Depth Глубина LFO + ADSR ADSR + Pressure Давление + Motion Движение + Speed Скорость + Bowed Наклон + Spread Разброс + Marimba Маримба + Vibraphone Вибрафон + Agogo Дискотека + Wood1 Дерево1 + Reso Резо + Wood2 Дерево2 + Beats Удары + Two Fixed Два фиксированных + Clump Тяжёлая поступь + Tubular Bells Трубные колокола + Uniform Bar Равномерные полосы + Tuned Bar Подстроенные полосы + Glass Стекло + Tibetan Bowl Тибетские шары @@ -8721,149 +11009,186 @@ Double clicking any of the plugins will bring up information on the ports. malletsInstrumentView + Instrument Инструмент + Spread Разброс + Spread: Разброс: - Hardness - Жёсткость - - - Hardness: - Жёсткость: - - - Position - Положение - - - Position: - Положение: - - - Vib Gain - Усил. вибрато - - - Vib Gain: - Усил. вибрато: - - - Vib Freq - Част. виб - - - Vib Freq: - Вибрато: - - - Stick Mix - Сведение ручек - - - Stick Mix: - Сведение ручек: - - - Modulator - Модулятор - - - Modulator: - Модулятор: - - - Crossfade - Переход - - - Crossfade: - Переход: - - - LFO Speed - Скорость LFO - - - LFO Speed: - Скорость LFO: - - - LFO Depth - Глубина LFO - - - LFO Depth: - Глубина LFO: - - - ADSR - ADSR - - - ADSR: - ADSR: - - - Pressure - Давление - - - Pressure: - Давление: - - - Speed - Скорость - - - Speed: - Скорость: - - + Missing files Файлы отсутствуют + Your Stk-installation seems to be incomplete. Please make sure the full Stk-package is installed! Похоже устновка Stk прошла не полностью. Пожалуйста, убедитесь, что пакет Stk полностью установлен! + + + Hardness + Жёсткость + + + + Hardness: + Жёсткость: + + + + Position + Положение + + + + Position: + Положение: + + + + Vib Gain + Усил. вибрато + + + + Vib Gain: + Усил. вибрато: + + + + Vib Freq + Част. виб + + + + Vib Freq: + Вибрато: + + + + Stick Mix + Сведение ручек + + + + Stick Mix: + Сведение ручек: + + + + Modulator + Модулятор + + + + Modulator: + Модулятор: + + + + Crossfade + Переход + + + + Crossfade: + Переход: + + + + LFO Speed + Скорость LFO + + + + LFO Speed: + Скорость LFO: + + + + LFO Depth + Глубина LFO + + + + LFO Depth: + Глубина LFO: + + + + ADSR + ADSR + + + + ADSR: + ADSR: + + + + Pressure + Давление + + + + Pressure: + Давление: + + + + Speed + Скорость + + + + Speed: + Скорость: + manageVSTEffectView + - VST parameter control Управление VST параметрами + VST Sync VST синхронизация + Click here if you want to synchronize all parameters with VST plugin. - Нажмите здесь для синхронизации всех параметров с VST плагином. + Нажмите здесь для синхронизации всех параметров VST плагина. + + Automated Автоматизировано + Click here if you want to display automated parameters only. Нажмите здесь, если хотите видеть только автоматизированные параметры. + Close Закрыть + Close VST effect knob-controller window. Закрыть окно управления регуляторами VST эффектов. @@ -8871,30 +11196,39 @@ Double clicking any of the plugins will bring up information on the ports. manageVestigeInstrumentView + + - VST plugin control Управление VST плагином + VST Sync VST синхронизация + Click here if you want to synchronize all parameters with VST plugin. Нажмите здесь для синхронизации всех параметров VST плагина. + + Automated Автоматизировано + Click here if you want to display automated parameters only. Нажмите здесь, если хотите видеть только автоматизированные параметры. + Close Закрыть + Close VST plugin knob-controller window. Закрыть окно управления регуляторами VST плагина. @@ -8902,118 +11236,147 @@ Double clicking any of the plugins will bring up information on the ports. opl2instrument + Patch Патч + Op 1 Attack ОП 1 Вступление + Op 1 Decay ОП 1 Спад + Op 1 Sustain ОП 1 Выдержка + Op 1 Release ОП 1 Убывание + Op 1 Level ОП 1 Уровень + Op 1 Level Scaling ОП 1 Уровень увеличения + Op 1 Frequency Multiple ОП 1 Множитель частот + Op 1 Feedback ОП 1 Возврат + Op 1 Key Scaling Rate ОП 1 Ключевая ставка увеличения + Op 1 Percussive Envelope ОП 1 Ударная огибающая + Op 1 Tremolo ОП 1 Тремоло + Op 1 Vibrato Оп 1 Вибрато + Op 1 Waveform ОП 1 Волна + Op 2 Attack ОП 2 Вступление + Op 2 Decay ОП 2 Спад + Op 2 Sustain ОП 2 Выдержка + Op 2 Release ОП 2 Убывание + Op 2 Level ОП 2 Уровень + Op 2 Level Scaling ОП 2 Уровень увеличения + Op 2 Frequency Multiple ОП 2 Множитель частот + Op 2 Key Scaling Rate ОП 2 Ключевая ставка множителя + Op 2 Percussive Envelope ОП 2 Ударная огибающая + Op 2 Tremolo ОП 2 Тремоло + Op 2 Vibrato Оп 2 Вибрато + Op 2 Waveform ОП 2 Волна + FM FM + Vibrato Depth Глубина вибрато + Tremolo Depth Глубина тремоло @@ -9021,29 +11384,39 @@ Double clicking any of the plugins will bring up information on the ports. opl2instrumentView + + Attack Вступление + + Decay Затихание + + Release Убывание + + Frequency multiplier - + Множитель частоты organicInstrument + Distortion Искажение + Volume Громкость @@ -9051,50 +11424,63 @@ Double clicking any of the plugins will bring up information on the ports. organicInstrumentView + Distortion: Искажение: - Volume: - Громкость: - - - Randomise - Случайно - - - Osc %1 waveform: - Форма сигнала для осциллятора %1: - - - Osc %1 volume: - Громкость осциллятора %1: - - - Osc %1 panning: - Баланс для осциллятора %1: - - - cents - сотые - - + The distortion knob adds distortion to the output of the instrument. Дисторшн добавляет искажения к выводу инструмента. + + Volume: + Громкость: + + + The volume knob controls the volume of the output of the instrument. It is cumulative with the instrument window's volume control. Регулятор громкости вывода инструмента, суммируется с регулятором громкости окна инструмента. + + Randomise + Случайно + + + The randomize button randomizes all knobs except the harmonics,main volume and distortion knobs. Кнопка рандомизации случайно устанавливает все регуляторы, кроме гармоник, основной громкости и регулятора искажений (дисторшн). + + + Osc %1 waveform: + Форма сигнала для осциллятора %1: + + + + Osc %1 volume: + Громкость осциллятора %1: + + + + Osc %1 panning: + Баланс для осциллятора %1: + + + Osc %1 stereo detuning Осц %1 стерео расстройка + + cents + сотые + + + Osc %1 harmonic: Осц %1 гармоника: @@ -9102,265 +11488,351 @@ Double clicking any of the plugins will bring up information on the ports. FreeBoyInstrument + Sweep time Время распространения + Sweep direction Направление распространения + Sweep RtShift amount - Кол-во распространения сдвига вправо + Кол-во развёртки сдвиг вправо + + Wave Pattern Duty Рабочая форма волны + Channel 1 volume Громкость первого канала + + + Volume sweep direction Объём направления распространения + + + Length of each step in sweep Длина каждого такта в распространении + Channel 2 volume Громкость второго канала + Channel 3 volume Громкость третьего канала + Channel 4 volume Громкость четвёртого канала + + Shift Register width + Сдвиг ширины регистра + + + Right Output level Выходной уровень справа + Left Output level Выходной уровень слева + Channel 1 to SO2 (Left) От первого канала к SO2 (левый канал) + Channel 2 to SO2 (Left) От второго канала к SO2 (левый канал) + Channel 3 to SO2 (Left) От третьего канала к SO2 (левый канал) + Channel 4 to SO2 (Left) От четвёртого канала к SO2 (левый канал) + Channel 1 to SO1 (Right) От первого канала к SO1 (правый канал) + Channel 2 to SO1 (Right) От второго канала к SO1 (правый канал) + Channel 3 to SO1 (Right) От третьего канала к SO1 (правый канал) + Channel 4 to SO1 (Right) От четвёртого канала к SO1 (правый канал) + Treble Верхние + Bass Нижние - - Shift Register width - Сдвиг ширины регистра - FreeBoyInstrumentView + Sweep Time: Время развёртки: + Sweep Time Время развёртки - Sweep RtShift amount: - Кол-во развёртки сдвиг вправо: - - - Sweep RtShift amount - Кол-во развёртки сдвиг вправо - - - Wave pattern duty: - Рабочая форма волны: - - - Wave Pattern Duty - Рабочая форма волны - - - Square Channel 1 Volume: - Громкость квадратного канала 1: - - - Length of each step in sweep: - Длина каждого такта в развёртке: - - - Length of each step in sweep - Длина каждого такта в распространении - - - Wave pattern duty - Рабочая форма волны - - - Square Channel 2 Volume: - Громкость квадратного канала 2: - - - Square Channel 2 Volume - Громкость квадратного канала 2 - - - Wave Channel Volume: - Громкость волнового канала: - - - Wave Channel Volume - Громкость волнового канала - - - Noise Channel Volume: - Громкость канала шума: - - - Noise Channel Volume - Громкость канала шума - - - SO1 Volume (Right): - Громкость SO1 (Правый): - - - SO1 Volume (Right) - Громкость SO1 (Правый) - - - SO2 Volume (Left): - Громкость SO2 (Левый): - - - SO2 Volume (Left) - Громкость SO2 (Левый) - - - Treble: - Верхние: - - - Treble - Верхние - - - Bass: - Нижние: - - - Bass - Нижние - - - Sweep Direction - Направление развёртки - - - Volume Sweep Direction - Громкость направления развёртки - - - Shift Register Width - Сдвиг ширины регистра - - - Channel1 to SO1 (Right) - Канал1 в SO1 (Правый) - - - Channel2 to SO1 (Right) - Канал2 в SO1 (Правый) - - - Channel3 to SO1 (Right) - Канал3 в SO1 (Правый) - - - Channel4 to SO1 (Right) - Канал4 в SO1 (Правый) - - - Channel1 to SO2 (Left) - Канал1 в SO2 (Левый) - - - Channel2 to SO2 (Left) - Канал2 в SO2 (Левый) - - - Channel3 to SO2 (Left) - Канал2 в SO2 (Левый) - - - Channel4 to SO2 (Left) - Канал4 в SO2 (Левый) - - - Wave Pattern - Рисунок волны - - + The amount of increase or decrease in frequency Кол-во увеличения или уменьшения в частоте + + Sweep RtShift amount: + Кол-во развёртки сдвиг вправо: + + + + Sweep RtShift amount + Кол-во развёртки сдвиг вправо + + + The rate at which increase or decrease in frequency occurs Темп проявления увеличения или снижения в частоте + + + Wave pattern duty: + Рабочая форма волны: + + + + Wave Pattern Duty + Рабочая форма волны + + + + The duty cycle is the ratio of the duration (time) that a signal is ON versus the total period of the signal. Рабочий цикл это коэффициент длительности (времени) включенного сигнала относительно всего периода сигнала. + + + Square Channel 1 Volume: + Громкость квадратного канала 1: + + + Square Channel 1 Volume Громкость квадратного канала 1 + + + + Length of each step in sweep: + Длина каждого такта в развёртке: + + + + + + Length of each step in sweep + Длина каждого такта в распространении + + + + + The delay between step change Задержка между изменениями такта + + Wave pattern duty + Рабочая форма волны + + + + Square Channel 2 Volume: + Громкость квадратного канала 2: + + + + + Square Channel 2 Volume + Громкость квадратного канала 2 + + + + Wave Channel Volume: + Громкость волнового канала: + + + + + Wave Channel Volume + Громкость волнового канала + + + + Noise Channel Volume: + Громкость канала шума: + + + + + Noise Channel Volume + Громкость канала шума + + + + SO1 Volume (Right): + Громкость SO1 (Правый): + + + + SO1 Volume (Right) + Громкость SO1 (Правый) + + + + SO2 Volume (Left): + Громкость SO2 (Левый): + + + + SO2 Volume (Left) + Громкость SO2 (Левый) + + + + Treble: + Верхние: + + + + Treble + Верхние + + + + Bass: + Нижние: + + + + Bass + Нижние + + + + Sweep Direction + Направление развёртки + + + + + + + + Volume Sweep Direction + Громкость направления развёртки + + + + Shift Register Width + Сдвиг ширины регистра + + + + Channel1 to SO1 (Right) + Канал1 в SO1 (Правый) + + + + Channel2 to SO1 (Right) + Канал2 в SO1 (Правый) + + + + Channel3 to SO1 (Right) + Канал3 в SO1 (Правый) + + + + Channel4 to SO1 (Right) + Канал4 в SO1 (Правый) + + + + Channel1 to SO2 (Left) + Канал1 в SO2 (Левый) + + + + Channel2 to SO2 (Left) + Канал2 в SO2 (Левый) + + + + Channel3 to SO2 (Left) + Канал2 в SO2 (Левый) + + + + Channel4 to SO2 (Left) + Канал4 в SO2 (Левый) + + + + Wave Pattern + Рисунок волны + + + Draw the wave here Рисовать волну здесь @@ -9368,34 +11840,42 @@ Double clicking any of the plugins will bring up information on the ports. patchesDialog + Qsynth: Channel Preset + Bank selector - + Выбор банка + Bank Банк + Program selector Выбор программ + Patch Патч + Name Имя + OK ОК + Cancel Отмена @@ -9403,186 +11883,231 @@ Double clicking any of the plugins will bring up information on the ports. pluginBrowser + no description описание отсутствует - Incomplete monophonic imitation tb303 - Незавершённая монофоническая имитация tb303 + + A native amplifier plugin + Родной плагин усилителя - Plugin for freely manipulating stereo output - Модуль для произвольного управления стереовыходом + + Simple sampler with various settings for using samples (e.g. drums) in an instrument-track + Простой сэмплер с разными установками по использованию сэмплов (как барабаны) в инструментальной дорожке - Plugin for controlling knobs with sound peaks - Модуль для установки значений регуляторов по пикам громкости + + Boost your bass the fast and simple way + Накачай свой бас быстро и просто - Plugin for enhancing stereo separation of a stereo input file - Модуль, усиливающий разницу между каналами стереозаписи + + Customizable wavetable synthesizer + Настраиваемый синтезатор звукозаписей (wavetable) + + An oversampling bitcrusher + + + + + Carla Patchbay Instrument + + + + + Carla Rack Instrument + Карла инструментальная стойка + + + + A 4-band Crossover Equalizer + + + + + A native delay plugin + Встроенный delay плагин + + + + A Dual filter plugin + Двух фильтровый плагин + + + + plugin for processing dynamics in a flexible way + + + + + A native eq plugin + Родной плагин эквалайзера + + + + A native flanger plugin + + + + + Player for GIG files + Проигрыватель GIG-файлов + + + + Filter for importing Hydrogen files into LMMS + Фильтр для импорта Hydrogen файлов в LMMS + + + + Versatile drum synthesizer + Универсальный барабанный синтезатор + + + List installed LADSPA plugins Показать установленные модули LADSPA - GUS-compatible patch instrument - Патч-инструмент, совместимый с GUS - - - Additive Synthesizer for organ-like sounds - Синтезатор звуков вроде органа - - - Tuneful things to bang on - Мелодичные ударные - - - VST-host for using VST(i)-plugins within LMMS - VST - хост для поддержки модулей VST(i) в LMMS - - - Vibrating string modeler - Эмуляция вибрирующих струн - - + plugin for using arbitrary LADSPA-effects inside LMMS. Модуль, позволяющий использовать в LMMS любые эффекты LADSPA. + + Incomplete monophonic imitation tb303 + Незавершённая монофоническая имитация tb303 + + + + Filter for exporting MIDI-files from LMMS + Фильтр для экспорта MIDI файлов из LMMS + + + Filter for importing MIDI-files into LMMS Фильтр для включения файла MIDI в проект ЛММС + + Monstrous 3-oscillator synth with modulation matrix + Монстро 3-осциляторный синт с матрицей модуляции + + + + A multitap echo delay plugin + + + + + A NES-like synthesizer + Синтезатор типа NES + + + + 2-operator FM Synth + 2-режимный синт модуляции частот (FM synth) + + + + Additive Synthesizer for organ-like sounds + Синтезатор звуков вроде органа + + + + Emulation of GameBoy (TM) APU + Эмуляция GameBoy (TM) + + + + GUS-compatible patch instrument + Патч-инструмент, совместимый с GUS + + + + Plugin for controlling knobs with sound peaks + Модуль для установки значений регуляторов по пикам громкости + + + + Reverb algorithm by Sean Costello + + + + + Player for SoundFont files + Проигрыватель файлов SoundFont + + + + LMMS port of sfxr + LMMS порт SFXR + + + Emulation of the MOS6581 and MOS8580 SID. This chip was used in the Commodore 64 computer. Эмуляция MOS6581 и MOS8580. Использовалось на компьютере Commodore 64. - Player for SoundFont files - Проигрыватель файлов SoundFont - - - Emulation of GameBoy (TM) APU - Эмуляция GameBoy (TM) - - - Customizable wavetable synthesizer - Настраиваемый синтезатор звукозаписей (wavetable) - - - Embedded ZynAddSubFX - Встроенный ZynAddSubFX - - - 2-operator FM Synth - 2-режимный синт модуляции частот (FM synth) - - - Filter for importing Hydrogen files into LMMS - Фильтр для импорта Hydrogen файлов в LMMS - - - LMMS port of sfxr - LMMS порт SFXR - - - Monstrous 3-oscillator synth with modulation matrix - Монстро 3-осциляторный синт с матрицей модуляции - - - Three powerful oscillators you can modulate in several ways - Три мощных осциллятора, которые можно модулировать несколькими способами - - - A native amplifier plugin - Родной плагин усилителя - - - Carla Rack Instrument - Карла инструментальная стойка - - - 4-oscillator modulatable wavetable synth - - - - plugin for waveshaping - Плагин для сглаживания волн - - - Boost your bass the fast and simple way - Накачай свой бас быстро и просто - - - Versatile drum synthesizer - - - - Simple sampler with various settings for using samples (e.g. drums) in an instrument-track - Простой сэмплер с разными установками по использованию сэмплов (как барабаны) в инструментальной дорожке - - - plugin for processing dynamics in a flexible way - - - - Carla Patchbay Instrument - - - - plugin for using arbitrary VST effects inside LMMS. - Плагин для использования любых VST эффектов в ЛММС - - + Graphical spectrum analyzer plugin Плагин графического анализа спектра - A NES-like synthesizer - Синтезатор типа NES + + Plugin for enhancing stereo separation of a stereo input file + Модуль, усиливающий разницу между каналами стереозаписи - A native delay plugin - + + Plugin for freely manipulating stereo output + Модуль для произвольного управления стереовыходом - Player for GIG files - + + Tuneful things to bang on + Мелодичные ударные - A multitap echo delay plugin - + + Three powerful oscillators you can modulate in several ways + Три мощных осциллятора, которые можно модулировать несколькими способами - A native flanger plugin - + + VST-host for using VST(i)-plugins within LMMS + VST - хост для поддержки модулей VST(i) в LMMS - An oversampling bitcrusher - + + Vibrating string modeler + Эмуляция вибрирующих струн - A native eq plugin - Родной плагин эквалайзера + + plugin for using arbitrary VST effects inside LMMS. + Плагин для использования любых VST эффектов в ЛММС - A 4-band Crossover Equalizer - + + 4-oscillator modulatable wavetable synth + 4-осцилляторный модулируемый волновой синтезатор - A Dual filter plugin - + + plugin for waveshaping + Плагин для сглаживания волн - Filter for exporting MIDI-files from LMMS - - - - Reverb algorithm by Sean Costello - + + Embedded ZynAddSubFX + Встроенный ZynAddSubFX Mathematical expression parser @@ -9592,58 +12117,72 @@ This chip was used in the Commodore 64 computer. sf2Instrument + Bank Банк + Patch Патч + Gain Усиление + Reverb Эхо + Reverb Roomsize Объём эха + Reverb Damping Затухание эха + Reverb Width Долгота эха + Reverb Level Уровень эха + Chorus Хор (припев) + Chorus Lines Линии хора + Chorus Level Уровень хора + Chorus Speed Скорость хора + Chorus Depth Глубина хора + A soundfont %1 could not be loaded. Soundfont %1 не удаётся загрузить. @@ -9651,74 +12190,92 @@ This chip was used in the Commodore 64 computer. sf2InstrumentView + Open other SoundFont file Открыть другой файл SoundFront + Click here to open another SF2 file Нажмите здесь чтобы открыть другой файл SF2 + Choose the patch Выбрать патч + Gain - Усиление + УСИЛ + Apply reverb (if supported) Создать эхо (если поддерживается) + This button enables the reverb effect. This is useful for cool effects, but only works on files that support it. Эта кнопка включает эффект эха. Это может пригодиться, но работает не для всех файлов. + Reverb Roomsize: Размер помещения: + Reverb Damping: Глушение эха: + Reverb Width: Долгота эха: + Reverb Level: Уровень эха: + Apply chorus (if supported) Создать эффект хора (если поддерживается) + This button enables the chorus effect. This is useful for cool echo effects, but only works on files that support it. Эта кнопка включает эффект хора. Это может пригодиться, но работает не для всех файлов. + Chorus Lines: Линии хора: + Chorus Level: Уровень хора: + Chorus Speed: Скорость хора: + Chorus Depth: Глубина хора: + Open SoundFont file Открыть файл SoundFront + SoundFont2 Files (*.sf2) Файлы SoundFont2 (*.sf2) @@ -9726,6 +12283,7 @@ This chip was used in the Commodore 64 computer. sfxrInstrument + Wave Form Форма волны @@ -9733,26 +12291,32 @@ This chip was used in the Commodore 64 computer. sidInstrument + Cutoff Срез + Resonance Усиление + Filter type Тип фильтра + Voice 3 off Голос 3 откл + Volume Громкость + Chip model Модель чипа @@ -9760,134 +12324,172 @@ This chip was used in the Commodore 64 computer. sidInstrumentView + Volume: Громкость: + Resonance: Усиление: + + Cutoff frequency: Частота среза: + High-Pass filter Выс.ЧФ + Band-Pass filter Сред.ЧФ + Low-Pass filter Низ.ЧФ + Voice3 Off Голос 3 откл + MOS6581 SID - + MOS6581 SID + MOS8580 SID - + MOS8580 SID + + Attack: Вступление: + Attack rate determines how rapidly the output of Voice %1 rises from zero to peak amplitude. Длительность вступления определяет, насколько быстро громкость %1-го голоса возрастает от нуля до наибольшего значения. + + Decay: - Спад: + Затухание: + Decay rate determines how rapidly the output falls from the peak amplitude to the selected Sustain level. Длительность спада определяет, насколько быстро громкость падает от максимума до остаточного уровня. + Sustain: Выдержка: + Output of Voice %1 will remain at the selected Sustain amplitude as long as the note is held. Громкость %1-го голоса будет оставаться на уровне амплитуды выдержки, пока длится нота. + + Release: Убывание: + The output of of Voice %1 will fall from Sustain amplitude to zero amplitude at the selected Release rate. Громкость %1-го голоса будет падать от остаточного уровня до нуля с указанной здесь скоростью. + + Pulse Width: Длительность импульса: + The Pulse Width resolution allows the width to be smoothly swept with no discernable stepping. The Pulse waveform on Oscillator %1 must be selected to have any audible effect. Длительность импульса позволяет мягко регулировать прохождение импульса без заметных сбоев. Импульсная волна должна быть выбрана на осцилляторе %1, чтобы получить звучание. + Coarse: Грубость: + The Coarse detuning allows to detune Voice %1 one octave up or down. Грубая настройка позволяет подстроить Голос %1 на одну октаву вверх или вниз. + Pulse Wave Пульсирующая волна + Triangle Wave Треугольник + SawTooth Зигзаг + Noise Шум + Sync Синхро + Sync synchronizes the fundamental frequency of Oscillator %1 with the fundamental frequency of Oscillator %2 producing "Hard Sync" effects. Синхро синхронизирует фундаментальную частоту осцилляторов %1 фундаментальной частотой осциллятора %2, создавая эффект "Железной синхронизации". + Ring-Mod Круговой режим + Ring-mod replaces the Triangle Waveform output of Oscillator %1 with a "Ring Modulated" combination of Oscillators %1 and %2. Круговой режим заменяет треугольные волны на выходе осциллятора %1 "Круговой модуляцией" комбинацией осцилляторов %1 и %2. + Filtered Фильтровать + When Filtered is on, Voice %1 will be processed through the Filter. When Filtered is off, Voice %1 appears directly at the output, and the Filter has no effect on it. Если этот флажок установлен, то %1-й голос будет проходить через фильтр. Иначе голос №%1 будет подаваться прямо на выход. + Test Тест + Test, when set, resets and locks Oscillator %1 at zero until Test is turned off. Если «флажок» установлен, то %1-й осциллятор выдаёт нулевой сигнал (пока флажок не снимется). @@ -9895,10 +12497,12 @@ This chip was used in the Commodore 64 computer. stereoEnhancerControlDialog + WIDE ШИРЕ + Width: Ширина: @@ -9906,6 +12510,7 @@ This chip was used in the Commodore 64 computer. stereoEnhancerControls + Width Ширина @@ -9913,18 +12518,22 @@ This chip was used in the Commodore 64 computer. stereoMatrixControlDialog + Left to Left Vol: От левого на левый: + Left to Right Vol: От левого на правый: + Right to Left Vol: От правого на левый: + Right to Right Vol: От правого на правый: @@ -9932,18 +12541,22 @@ This chip was used in the Commodore 64 computer. stereoMatrixControls + Left to Left От левого на левый + Left to Right От левого на правый + Right to Left От правого на левый + Right to Right От правого на правый @@ -9951,10 +12564,12 @@ This chip was used in the Commodore 64 computer. vestigeInstrument + Loading plugin Загрузка модуля + Please wait while loading VST-plugin... Подождите, пока загрузится модуль VST... @@ -9962,42 +12577,52 @@ This chip was used in the Commodore 64 computer. vibed + String %1 volume Громкость %1-й струны + String %1 stiffness Жёсткость %1-й струны + Pick %1 position Лад %1 + Pickup %1 position Положение %1-го звукоснимателя + Pan %1 Бал %1 + Detune %1 Подстройка %1 + Fuzziness %1 Нечёткость %1 + Length %1 Длина %1 + Impulse %1 Импульс %1 + Octave %1 Октава %1 @@ -10005,90 +12630,112 @@ This chip was used in the Commodore 64 computer. vibedView + Volume: Громкость: + The 'V' knob sets the volume of the selected string. Регулятор 'V' устанавливает громкость текущей струны. + String stiffness: Жёсткость: + The 'S' knob sets the stiffness of the selected string. The stiffness of the string affects how long the string will ring out. The lower the setting, the longer the string will ring. Регулятор 'S' устанавливает жёсткость текущей струны. Этот параметр отвечает за длительность звучания струны (чем больше значение жёсткости, тем дольше звенит струна). + Pick position: Лад: + The 'P' knob sets the position where the selected string will be 'picked'. The lower the setting the closer the pick is to the bridge. Регулятор 'P' устанавливает место струны, где она будет „прижата“. Чем ниже значение, тем ближе это место будет к кобылке. + Pickup position: Положение звукоснимателя: + The 'PU' knob sets the position where the vibrations will be monitored for the selected string. The lower the setting, the closer the pickup is to the bridge. Регулятор 'PU' устанавливает место струны, откуда будет сниматься звук. Чем ниже значение, тем ближе это место будет к кобылке. + Pan: Бал: + The Pan knob determines the location of the selected string in the stereo field. Эта ручка устанавливает стереобаланс для текущей струны. + Detune: Подстроить: + The Detune knob modifies the pitch of the selected string. Settings less than zero will cause the string to sound flat. Settings greater than zero will cause the string to sound sharp. Ручка подстройки изменяет сдвиг частоты для текущей струны. Отрицательные значения заставят струну звучать плоско (бемольно), положительные — остро (диезно). + Fuzziness: Нечёткость: + The Slap knob adds a bit of fuzz to the selected string which is most apparent during the attack, though it can also be used to make the string sound more 'metallic'. Эта ручка добавляет размытости звуку, что наиболее заметно во время нарастания, впрочем, это может использоваться, чтобы сделать звук более „металлическим“. + Length: Длина: + The Length knob sets the length of the selected string. Longer strings will both ring longer and sound brighter, however, they will also eat up more CPU cycles. Ручка длины устанавливает длину текущей струны. Чем длиннее струна, тем более чистый и долгий звук она даёт; однако это требует больше ресурсов ЦП. + Impulse or initial state Начальная скорость/начальное состояние + The 'Imp' selector determines whether the waveform in the graph is to be treated as an impulse imparted to the string by the pick or the initial state of the string. Переключатель „Imp“ устанавливает режим работы струны: если он включён, то указанная форма сигнала интерпретируется как начальный импульс, иначе — как начальная форма струны. + Octave Октава + The Octave selector is used to choose which harmonic of the note the string will ring at. For example, '-2' means the string will ring two octaves below the fundamental, 'F' means the string will ring at the fundamental, and '6' means the string will ring six octaves above the fundamental. Переключатель октав позволяет указать гармонику основной частоты, на которой будет звучать струна. Например, „-2“ означает, что струна будет звучать двумя октавами ниже основной частоты, „F“ заставит струну звенеть на основной частоте инструмента, а „6“ — на частоте, на шесть октав более высокой, чем основная. + Impulse Editor Редактор сигнала + The waveform editor provides control over the initial state or impulse that is used to start the string vibrating. The buttons to the right of the graph will initialize the waveform to the selected type. The '?' button will load a waveform from a file--only the first 128 samples will be loaded. The waveform can also be drawn in the graph. @@ -10106,6 +12753,7 @@ The 'N' button will normalize the waveform. Кнопка 'N' нормализует уровень. + Vibed models up to nine independently vibrating strings. The 'String' selector allows you to choose which string is being edited. The 'Imp' selector chooses whether the graph represents an impulse or the initial state of the string. The 'Octave' selector chooses which harmonic the string should vibrate at. The graph allows you to control the initial state or impulse used to set the string in motion. @@ -10136,129 +12784,160 @@ The LED in the lower right corner of the waveform editor determines whether the Индикатор-переключатель слева внизу определяет, включена ли текущая струна. + Enable waveform Включить + Click here to enable/disable waveform. Нажмите, чтобы включить/выключить сигнал. + String Струна + The String selector is used to choose which string the controls are editing. A Vibed instrument can contain up to nine independently vibrating strings. The LED in the lower right corner of the waveform editor indicates whether the selected string is active. Переключатель струн позволяет выбрать струну, чьи свойства редактируются. Инструмент Vibed содержит до девяти независимо звучащих струн, индикатор в левом нижнем углу показывает, активна ли текущая струна (т. е. будет ли она слышна). + Sine wave Синусоида - Triangle wave - Треугольник - - - Saw wave - Зигзаг - - - Square wave - Квадратная волна - - - White noise wave - Белый шум - - - User defined wave - Пользовательская - - - Smooth - Сгладить - - - Click here to smooth waveform. - Щёлкните чтобы сгладить форму сигнала. - - - Normalize - Нормализовать - - - Click here to normalize waveform. - Нажмите, чтобы нормализовать сигнал. - - + Use a sine-wave for current oscillator. Генерировать гармонический (синусоидальный) сигнал. + + Triangle wave + Треугольник + + + Use a triangle-wave for current oscillator. Генерировать треугольный сигнал. + + Saw wave + Зигзаг + + + Use a saw-wave for current oscillator. Генерировать зигзагообразный сигнал. + + Square wave + Квадратная волна + + + Use a square-wave for current oscillator. Генерировать квадрат (меандр). + + White noise wave + Белый шум + + + Use white-noise for current oscillator. Генерировать белый шум. + + User defined wave + Пользовательская + + + Use a user-defined waveform for current oscillator. Задать форму сигнала. + + + Smooth + Сгладить + + + + Click here to smooth waveform. + Щёлкните чтобы сгладить форму сигнала. + + + + Normalize + Нормализовать + + + + Click here to normalize waveform. + Нажмите, чтобы нормализовать сигнал. + voiceObject + Voice %1 pulse width Голос %1 длина сигнала + Voice %1 attack Вступление %1-го голоса + Voice %1 decay - Спад %1-го голоса + Затухание %1-го голоса + Voice %1 sustain Выдержка для %1-го голоса + Voice %1 release Убывание %1-го голоса + Voice %1 coarse detuning Подстройка %1-го голоса (грубо) + Voice %1 wave shape Форма сигнала для %1-го голоса + Voice %1 sync Синхронизация %1-го голоса + Voice %1 ring modulate Голос %1 кольцевой модулятор + Voice %1 filtered Фильтрованный %1-й голос + Voice %1 test Голос %1 тест @@ -10266,58 +12945,72 @@ The LED in the lower right corner of the waveform editor determines whether the waveShaperControlDialog + INPUT ВХОД + Input gain: Входная мощность: + OUTPUT Выход + Output gain: Выходная мощность: + Reset waveform Сбросить волну + Click here to reset the wavegraph back to default Сбросить граф волны обратно по умолчанию + Smooth waveform Сгладить волну + Click here to apply smoothing to wavegraph Применить сглаживание к графу волны + Increase graph amplitude by 1dB - + Повысить амплитуду графа на 1 дБ + Click here to increase wavegraph amplitude by 1dB - Повыситьить амплитуду графа волны на 1дБ + Нажмите здесь, чтобы повысить амплитуду графа волны на 1 дБ + Decrease graph amplitude by 1dB - + Снизить амплитуду графа на 1 дБ + Click here to decrease wavegraph amplitude by 1dB - Снизить амплитуду графа волны на 1дБ + Снизить амплитуду графа волны на 1 дБ + Clip input Срезать выходной сигнал + Clip input signal to 0dB Срезать входной сигнал до 0дБ @@ -10325,12 +13018,14 @@ The LED in the lower right corner of the waveform editor determines whether the waveShaperControls + Input gain Входная мощность + Output gain Выходная мощность - \ No newline at end of file + diff --git a/data/locale/sv.ts b/data/locale/sv.ts index 3b75e54c0..56cf1a0af 100644 --- a/data/locale/sv.ts +++ b/data/locale/sv.ts @@ -2,121 +2,148 @@ AboutDialog + About LMMS Om LMMS + + LMMS + LMMS + + + Version %1 (%2/%3, Qt %4, %5) Version %1 (%2/%3, Qt %4, %5) + About Om + LMMS - easy music production for everyone LMMS - enkel musikproduktion för alla - Authors - Medverkande + + Copyright © %1 + Copyright © %1 + + <html><head/><body><p><a href="https://lmms.io"><span style=" text-decoration: underline; color:#0000ff;">https://lmms.io</span></a></p></body></html> + <html><head/><body><p><a href="https://lmms.io"><span style=" text-decoration: underline; color:#0000ff;">https://lmms.io</span></a></p></body></html> + + + + Authors + Upphovsmän + + + + Involved + Engagerade + + + + Contributors ordered by number of commits: + Bidragsgivare ordnade efter mängd bidrag: + + + Translation Översättning + Current language not translated (or native English). If you're interested in translating LMMS in another language or want to improve existing translations, you're welcome to help us! Simply contact the maintainer! + License Licens - - LMMS - LMMS - - - Involved - Involverad - - - Contributors ordered by number of commits: - Medverkande, ordnade efter mängd bidrag: - - - Copyright © %1 - Copyright © %1 - - - <html><head/><body><p><a href="https://lmms.io"><span style=" text-decoration: underline; color:#0000ff;">https://lmms.io</span></a></p></body></html> - - AmplifierControlDialog + VOL VOL + Volume: Volym: + PAN - PANORERA + PAN + Panning: Panorering: + LEFT VÄNSTER + Left gain: - Vänster förstärkning: + Vänsterförstärkning: + RIGHT HÖGER + Right gain: - Höger förstärkning: + Högerförstärkning: AmplifierControls + Volume Volym + Panning Panorering + Left gain - Vänster förstärkning + Vänsterförstärkning + Right gain - Höger förstärkning + Högerförstärkning AudioAlsaSetupWidget + DEVICE ENHET + CHANNELS KANALER @@ -124,78 +151,98 @@ If you're interested in translating LMMS in another language or want to imp AudioFileProcessorView + Open other sample Öppna annan ljudfil + Click here, if you want to open another audio-file. A dialog will appear where you can select your file. Settings like looping-mode, start and end-points, amplify-value, and so on are not reset. So, it may not sound like the original sample. Klicka här för att öppna en annan ljudfil. En dialog visas där du väljer din fil. Inställningar som looping, start och slutpunkter, amplifiering och sådant omställs inte. Därför låter det kanske inte som originalfilen. + Reverse sample Spela baklänges + If you enable this button, the whole sample is reversed. This is useful for cool effects, e.g. a reversed crash. - Den här knappen gör att ljudfilen spelas baklänges. Den kan användas för intressanta effeker t.ex. en baklänges cymbal. - - - Amplify: - Förstärkning: - - - With this knob you can set the amplify ratio. When you set a value of 100% your sample isn't changed. Otherwise it will be amplified up or down (your actual sample-file isn't touched!) - Med detta vred ställer du in förstärkningen. Vid 100% blir det ingen skillnad. Annars blir din ljudfil mer eller mindre högljudd, men originalfilen förändras inte. - - - Startpoint: - Startpunkt: - - - Endpoint: - Slutpunkt: - - - Continue sample playback across notes - Forsätt spela ljudfil över noter - - - Enabling this option makes the sample continue playing across different notes - if you change pitch, or the note length stops before the end of the sample, then the next note played will continue where it left off. To reset the playback to the start of the sample, insert a note at the bottom of the keyboard (< 20 Hz) - Denna inställningen gör att ljudfilen förtsätter spela över noter. Om en not avslutas före ljudfilen är slut fortsätter nästa not där den förra slutade. Om du vill starta från början av ljudfilen innan den spelat färdigt, placera en not på botten av pianot (vid 20Hz) + Den här knappen gör att ljudfilen spelas baklänges. Den kan användas för intressanta effekter t.ex. en baklänges cymbal. + Disable loop - Avaktivera looping + Inaktivera slinga + This button disables looping. The sample plays only once from start to end. Den här knappen avaktiverar looping. Ljudfilen spelas bara en gång från start till slut. + + Enable loop - Aktivera looping + Aktivera slinga + This button enables forwards-looping. The sample loops between the end point and the loop point. Den här knappen aktiverar looping. Ljudfilen loopar mellan slutpunkten och looppunkten. + This button enables ping-pong-looping. The sample loops backwards and forwards between the end point and the loop point. - Den här knappen aktiverar "ping-pong" looping. Ljudfilen spelar från start till slut, och sen tilbaks, och fortsäter så. + Den här knappen aktiverar "ping-pong" looping. Ljudfilen spelar från start till slut, och sen tillbaka, och fortsätter så. + + Continue sample playback across notes + Fortsätt spela ljudfil över noter + + + + Enabling this option makes the sample continue playing across different notes - if you change pitch, or the note length stops before the end of the sample, then the next note played will continue where it left off. To reset the playback to the start of the sample, insert a note at the bottom of the keyboard (< 20 Hz) + Denna inställningen gör att ljudfilen fortsätter spela över noter. Om en not avslutas före ljudfilen är slut fortsätter nästa not där den förra slutade. Om du vill starta från början av ljudfilen innan den spelat färdigt, placera en not på botten av pianot (vid 20Hz) + + + + Amplify: + Förstärkning: + + + + With this knob you can set the amplify ratio. When you set a value of 100% your sample isn't changed. Otherwise it will be amplified up or down (your actual sample-file isn't touched!) + Med detta vred ställer du in förstärkningen. Vid 100% blir det ingen skillnad. Annars blir din ljudfil mer eller mindre högljudd, men originalfilen förändras inte. + + + + Startpoint: + Startpunkt: + + + With this knob you can set the point where AudioFileProcessor should begin playing your sample. Med den här vreden ställer du in vartifrån ljudfilen ska börja spela. + + Endpoint: + Slutpunkt: + + + With this knob you can set the point where AudioFileProcessor should stop playing your sample. Med den här vreden ställer du in vart ljudfilen slutar spela. + Loopback point: - Loopback punkt: + Slinga-tillbaka punkt: + With this knob you can set the point where the loop starts. Den här vreden ställer in vart loopen startar. @@ -203,6 +250,7 @@ If you're interested in translating LMMS in another language or want to imp AudioFileProcessorWaveView + Sample length: Ljudfilens längd: @@ -210,26 +258,32 @@ If you're interested in translating LMMS in another language or want to imp AudioJack + JACK client restarted - JACK klienten omstartades + JACK-klienten omstartad + LMMS was kicked by JACK for some reason. Therefore the JACK backend of LMMS has been restarted. You will have to make manual connections again. - LMMS blev bortkopplat från JACK. LMMS JACK backend omstartades därfor. Du får manuellt koppla om igen. + LMMS blev bortkopplat från JACK. LMMS JACK backend omstartades därfor. Du behöver koppla om manuellt. + JACK server down JACK-server nerstängd + The JACK server seems to have been shutdown and starting a new instance failed. Therefore LMMS is unable to proceed. You should save your project and restart JACK and LMMS. JACK-servern stängdes ned och det gick inte starta en ny. LMMS kan inte fortsätta. Du bör spara ditt projekt och starta om både JACK och LMMS. + CLIENT-NAME KLIENT-NAMN + CHANNELS KANALER @@ -237,10 +291,12 @@ If you're interested in translating LMMS in another language or want to imp AudioOss::setupWidget + DEVICE ENHET + CHANNELS KANALER @@ -248,10 +304,12 @@ If you're interested in translating LMMS in another language or want to imp AudioPortAudio::setupWidget + BACKEND BACKEND + DEVICE ENHET @@ -259,10 +317,12 @@ If you're interested in translating LMMS in another language or want to imp AudioPulseAudio::setupWidget + DEVICE ENHET + CHANNELS KANALER @@ -270,6 +330,7 @@ If you're interested in translating LMMS in another language or want to imp AudioSdl::setupWidget + DEVICE ENHET @@ -277,10 +338,12 @@ If you're interested in translating LMMS in another language or want to imp AudioSndio::setupWidget + DEVICE ENHET + CHANNELS KANALER @@ -288,10 +351,12 @@ If you're interested in translating LMMS in another language or want to imp AudioSoundIo::setupWidget + BACKEND BAKÄNDE + DEVICE ENHET @@ -299,61 +364,75 @@ If you're interested in translating LMMS in another language or want to imp AutomatableModel + &Reset (%1%2) &Nollställ (%1%2) + &Copy value (%1%2) - Kopiera värde (%1%2) + &Kopiera värde (%1%2) + &Paste value (%1%2) &Klistra in värde (%1%2) + Edit song-global automation - Redigera global automation - - - Connected to %1 - Kopplad till %1 - - - Connected to controller - Kopplad till controller - - - Edit connection... - Redigera koppling... - - - Remove connection - Ta bort koppling - - - Connect to controller... - Koppla till kontroller... + Redigera låt-global automation + Remove song-global automation Ta bort global automation + Remove all linked controls Ta bort alla kopplade kontroller + + + Connected to %1 + Kopplad till %1 + + + + Connected to controller + Kopplad till controller + + + + Edit connection... + Redigera koppling... + + + + Remove connection + Ta bort koppling + + + + Connect to controller... + Koppla till kontroller... + AutomationEditor + Please open an automation pattern with the context menu of a control! - Öppna ett automationsmönster ifrån en kontrollers kontextmeny! + Öppna ett automationsmönster från en kontrollers kontextmeny! + Values copied Värden kopierade + All selected values were copied to the clipboard. Alla valda värden blev kopierade till urklipp. @@ -361,142 +440,184 @@ If you're interested in translating LMMS in another language or want to imp AutomationEditorWindow + Play/pause current pattern (Space) Spela/pausa aktuellt mönster (Mellanslag) + Click here if you want to play the current pattern. This is useful while editing it. The pattern is automatically looped when the end is reached. Klicka här för att spela det aktuella mönstret, detta är användbart när man redigerar. Mönstret spelas från början igen när det nått sitt slut. + Stop playing of current pattern (Space) - Sluta spela aktuellt mönster (mellanslag) + Sluta spela aktuellt mönster (Mellanslag) + Click here if you want to stop playing of the current pattern. Klicka här för att stoppa uppspelning av de aktuella mönstret. - Draw mode (Shift+D) - Ritläge (Shift+D) - - - Erase mode (Shift+E) - Suddläge (Shift+E) - - - Flip vertically - Spegla vertikalt - - - Flip horizontally - Spegla horizontellt - - - Click here and the pattern will be inverted.The points are flipped in the y direction. - Klicka här för att spegla mönstret. Punkterna förflyttas på y-axeln - - - Click here and the pattern will be reversed. The points are flipped in the x direction. - Klicka här för att spegla mönstret. Punkterna förflyttas på x-axeln - - - Click here and draw-mode will be activated. In this mode you can add and move single values. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. - Klicka här för att aktivera ritläget. I detta läget kan du lägga till och förflytta individuella värden. Det här är standardläget. Det går också att trycka 'Shift+D' på tangentborded för att aktivera detta läget. - - - Click here and erase-mode will be activated. In this mode you can erase single values. You can also press 'Shift+E' on your keyboard to activate this mode. - Klicka här för att aktivera suddläget. I detta läget kan du ta bort individuella värden. Det går också att trycka 'Shift+E' på tangentborded för att aktivera detta läget. - - - Discrete progression - Diskret talföljd - - - Linear progression - Linjär talföljd - - - Cubic Hermite progression - Cubic Hermite talföljd - - - Tension value for spline - Spänning i mönstrets spline - - - A higher tension value may make a smoother curve but overshoot some values. A low tension value will cause the slope of the curve to level off at each control point. - Högre spänning ger en mjuk kurva som ibland missar individuella punkter. Med lägre spänning planar kurvan ut nära punkterna. - - - Click here to choose discrete progressions for this automation pattern. The value of the connected object will remain constant between control points and be set immediately to the new value when each control point is reached. - Klicka här för att aktivera diskret talföljd. Värdet är konstant mella kontroll punkter och ändras direkt när en ny kontrollpunkt nås. - - - Click here to choose linear progressions for this automation pattern. The value of the connected object will change at a steady rate over time between control points to reach the correct value at each control point without a sudden change. - Klicka här för att aktivera linjär talföljd. Värdet ändras vid en stadig takt mellan kontrollpunkter för att gradvis nå nästa värde. - - - Click here to choose cubic hermite progressions for this automation pattern. The value of the connected object will change in a smooth curve and ease in to the peaks and valleys. - Klicka här för att aktivera cubic hermite talföljd. Värdet följer en mjuk kurva mellan kontrollpunkter. - - - Cut selected values (%1+X) - Klipp ut valda värden (%1+X) - - - Copy selected values (%1+C) - Kopiera valda värden (%1+C) - - - Paste values from clipboard (%1+V) - Klistra värden (%1+V) - - - Click here and selected values will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. - Klicka här för att klippa de valda värderna. Du kan sen klistra dem var som helst genom att klicka på klistra knappen. - - - Click here and selected values will be copied into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. - Klicka här för att kopiera de valda värderna. Du kan sedan klistra dem var som helst genom att klicka på klistra knappen. - - - Click here and the values from the clipboard will be pasted at the first visible measure. - Klicka här för att klistra kopierade värderna vid den första synliga metern. - - - Tension: - Spänning: - - - Automation Editor - no pattern - Redigera Automation - inget automationsmönster - - - Automation Editor - %1 - Redigera Automation - %1 - - + Edit actions Redigera åtgärder + + Draw mode (Shift+D) + Ritläge (Skift+D) + + + + Erase mode (Shift+E) + Suddläge (Skift+E) + + + + Flip vertically + Spegla vertikalt + + + + Flip horizontally + Spegla horizontellt + + + + Click here and the pattern will be inverted.The points are flipped in the y direction. + Klicka här för att spegla mönstret. Punkterna förflyttas på y-axeln + + + + Click here and the pattern will be reversed. The points are flipped in the x direction. + Klicka här för att spegla mönstret. Punkterna förflyttas på x-axeln + + + + Click here and draw-mode will be activated. In this mode you can add and move single values. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. + Klicka här för att aktivera ritläget. I detta läget kan du lägga till och förflytta individuella värden. Det här är standardläget. Det går också att trycka "Skift+D" på tangentbordet för att aktivera detta läget. + + + + Click here and erase-mode will be activated. In this mode you can erase single values. You can also press 'Shift+E' on your keyboard to activate this mode. + Klicka här för att aktivera suddläget. I detta läget kan du ta bort individuella värden. Det går också att trycka "Skift+E" på tangentbordet för att aktivera detta läget. + + + Interpolation controls Interpoleringskontroller - Timeline controls - Tidslinjekontroller + + Discrete progression + Diskret talföljd + + Linear progression + Linjär talföljd + + + + Cubic Hermite progression + Cubic Hermite talföljd + + + + Tension value for spline + Spänning i mönstrets spline + + + + A higher tension value may make a smoother curve but overshoot some values. A low tension value will cause the slope of the curve to level off at each control point. + Högre spänning ger en mjuk kurva som ibland missar individuella punkter. Med lägre spänning planar kurvan ut nära punkterna. + + + + Click here to choose discrete progressions for this automation pattern. The value of the connected object will remain constant between control points and be set immediately to the new value when each control point is reached. + Klicka här för att aktivera diskret talföljd. Värdet är konstant mella kontroll punkter och ändras direkt när en ny kontrollpunkt nås. + + + + Click here to choose linear progressions for this automation pattern. The value of the connected object will change at a steady rate over time between control points to reach the correct value at each control point without a sudden change. + Klicka här för att aktivera linjär talföljd. Värdet ändras vid en stadig takt mellan kontrollpunkter för att gradvis nå nästa värde. + + + + Click here to choose cubic hermite progressions for this automation pattern. The value of the connected object will change in a smooth curve and ease in to the peaks and valleys. + Klicka här för att aktivera cubic hermite talföljd. Värdet följer en mjuk kurva mellan kontrollpunkter. + + + + Tension: + Spänning: + + + + Cut selected values (%1+X) + Klipp ut valda värden (%1+X) + + + + Copy selected values (%1+C) + Kopiera valda värden (%1+C) + + + + Paste values from clipboard (%1+V) + Klistra värden (%1+V) + + + + Click here and selected values will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. + Klicka här för att klippa de valda värderna. Du kan sen klistra dem var som helst genom att klicka på klistra knappen. + + + + Click here and selected values will be copied into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. + Klicka här för att kopiera de valda värderna. Du kan sedan klistra dem var som helst genom att klicka på klistra knappen. + + + + Click here and the values from the clipboard will be pasted at the first visible measure. + Klicka här för att klistra kopierade värderna vid den första synliga metern. + + + Zoom controls Zoomningskontroller + Quantization controls + Kvantiseringskontroller + + + + Quantization + Kvantisering + + + + Quantization. Sets the smallest step size for the Automation Point. By default this also sets the length, clearing out other points in the range. Press <Ctrl> to override this behaviour. + + + Automation Editor - no pattern + Redigera Automation - inget automationsmönster + + + + + Automation Editor - %1 + Redigera Automation - %1 + + + Model is already connected to this pattern. Modellen är redan ansluten till det här mönstret. @@ -504,6 +625,7 @@ If you're interested in translating LMMS in another language or want to imp AutomationPattern + Drag a control while pressing <%1> Dra en kontroll samtidigt som du håller <%1> @@ -511,46 +633,57 @@ If you're interested in translating LMMS in another language or want to imp AutomationPatternView + double-click to open this pattern in automation editor dubbelklicka för att öppna det här automationsmönstret för redigering + Open in Automation editor Redigera automationsmönster + Clear Rensa + Reset name Nollställ namn + Change name Byt namn - %1 Connections - %1 Kopplingar - - - Disconnect "%1" - Avkoppla "%1" - - + Set/clear record + Flip Vertically (Visible) Spegla Vertikalt (Synligt) + Flip Horizontally (Visible) Spegla Horizontellt (Synligt) + + %1 Connections + %1 Kopplingar + + + + Disconnect "%1" + Koppla bort "%1" + + + Model is already connected to this pattern. Modellen är redan ansluten till det här mönstret. @@ -558,6 +691,7 @@ If you're interested in translating LMMS in another language or want to imp AutomationTrack + Automation track Automationsspår @@ -565,88 +699,108 @@ If you're interested in translating LMMS in another language or want to imp BBEditor + Beat+Bassline Editor - Redigera Trummor+Bas + Takt+Basgång-redigeraren + Play/pause current beat/bassline (Space) - Spela/pause Trummor+Bas + Spela/pausa nuvarande takt/basgång (Mellanslag) + Stop playback of current beat/bassline (Space) - Avsluta uppspelning av trummor/bas + Avsluta uppspelning av nuvarande takt/basgång (Mellanslag) + Click here to play the current beat/bassline. The beat/bassline is automatically looped when its end is reached. - Klicka här för att spela trummor/bas. Mönstret loopar när det nåt sitt slut. + Klicka här för att spela takt/basgång. Takt/basgång återupprepas automatiskt när dess slut nås. + Click here to stop playing of current beat/bassline. - Klicka här för att sluta spela trummor/bas. - - - Add beat/bassline - Lägg till trummor/bas - - - Add automation-track - Lägg till automationsspår - - - Remove steps - Ta bort steg - - - Add steps - Lägg till steg + Klicka här för att sluta spela takt/basgång. + Beat selector Taktväljare + Track and step actions Spår och stegåtgärder - Clone Steps - Klona steg + + Add beat/bassline + Lägg till takt/basgång + Add sample-track - Lägg till ljudfils-spår + Lägg till ljudspår + + + + Add automation-track + Lägg till automationsspår + + + + Remove steps + Ta bort steg + + + + Add steps + Lägg till steg + + + + Clone Steps + Klona steg BBTCOView + Open in Beat+Bassline-Editor - Redigera Trummor+Bas + Öppna Takt+Basgång-redigeraren + Reset name Nollställ namn + Change name Byt namn + Change color Byt färg + Reset color to default - Byt färg till standard + Nollställ färg till standard BBTrack + Beat/Bassline %1 - Trum/Basmönster %1 + Takt/Basgång %1 + Clone of %1 Kopia av %1 @@ -654,124 +808,149 @@ If you're interested in translating LMMS in another language or want to imp BassBoosterControlDialog + FREQ FREQ + Frequency: Frekvens: + GAIN - FÖRST + FÖRSTÄRKNING + Gain: Förstärkning: + RATIO - RATIO + FÖRHÅLLANDE + Ratio: - Ratio: + Förhållande: BassBoosterControls + Frequency Frekvens + Gain Förstärkning + Ratio - Ratio + Förhållande BitcrushControlDialog + IN IN + OUT UT + + GAIN - FÖRST + FÖRSTÄRKNING + Input Gain: - Input Förstärkning: + Ingång förstärkning: - NOIS - NOIS + + NOISE + BRUS + Input Noise: + Output Gain: Output Förstärkning + CLIP KLIPP + Output Clip: - Rate - Värdera - - + Rate Enabled - + Hastighet Aktiverad + Enable samplerate-crushing - Depth - Djup - - + Depth Enabled + Enable bitdepth-crushing + + FREQ + FREKV. + + + Sample rate: - + Samplingsfrekvens: - STD - STD + + STEREO + STEREO + Stereo difference: + Stereo skillnad: + + + + QUANT - Levels - Nivåer - - + Levels: Nivåer: @@ -779,10 +958,12 @@ If you're interested in translating LMMS in another language or want to imp CaptionMenu + &Help &Hjälp + Help (not available) Hjälp (inte tillgängligt) @@ -790,10 +971,12 @@ If you're interested in translating LMMS in another language or want to imp CarlaInstrumentView + Show GUI Visa användargränssnitt + Click here to show or hide the graphical user interface (GUI) of Carla. Klicka här för att visa eller gömma användargränssnittet för Carla. @@ -801,6 +984,7 @@ If you're interested in translating LMMS in another language or want to imp Controller + Controller %1 Kontroller %1 @@ -808,58 +992,73 @@ If you're interested in translating LMMS in another language or want to imp ControllerConnectionDialog + Connection Settings Kopplingsinställningar + MIDI CONTROLLER MIDI-KONTROLLER + Input channel - Inputkanal + Ingångskanal + CHANNEL KANAL + Input controller - Inputkontroller + Ingångsregulator + CONTROLLER KONTROLLER + + Auto Detect Upptäck Automatiskt + MIDI-devices to receive MIDI-events from - MIDI-enheter att ta emot MIDI-events från + MIDI-enheter för att ta emot MIDI-händelser från + USER CONTROLLER ANVÄNDARKONTROLLER + MAPPING FUNCTION - + KARTLÄGGNINGSFUNKTION + OK OK + Cancel Avbryt + LMMS LMMS + Cycle Detected. @@ -867,18 +1066,22 @@ If you're interested in translating LMMS in another language or want to imp ControllerRackView + Controller Rack Kontrollrack + Add Lägg till + Confirm Delete Bekräfta Borttagning + Confirm delete? There are existing connection(s) associated with this controller. There is no way to undo. Vill du verkligen ta bort? Det finns kopplingar till den här kontrollern, och operationen går inte ångra. @@ -886,93 +1089,115 @@ If you're interested in translating LMMS in another language or want to imp ControllerView + Controls Kontroller + Controllers are able to automate the value of a knob, slider, and other controls. Kontroller kan automatisera värdet på en vred, reglage, och andra kontroller + Rename controller Byt namn på kontroller + Enter the new name for this controller Skriv nya namnet på kontrollern + + LFO + LFO + + + &Remove this controller &Ta bort den här kontrollen + Re&name this controller Döp& om den här kontrollern - - LFO - LFO - CrossoverEQControlDialog + Band 1/2 Crossover: + Band 2/3 Crossover: + Band 3/4 Crossover: + Band 1 Gain: Band 1 Förstärkn.: + Band 2 Gain: Band 2 Förstärkn.: + Band 3 Gain: Band 3 Förstärkn.: + Band 4 Gain: Band 4 Förstärkn.: + Band 1 Mute Band 1 Tyst + Mute Band 1 Tysta Band 1 + Band 2 Mute Band 2 Tyst + Mute Band 2 Tysta Band 2 + Band 3 Mute Band 3 Tyst + Mute Band 3 Tysta Band 3 + Band 4 Mute Band 4 Tyst + Mute Band 4 Tysta Band 4 @@ -980,22 +1205,27 @@ If you're interested in translating LMMS in another language or want to imp DelayControls + Delay Samples - Fördröj Samplingar + Fördröj samplingar + Feedback Återkoppling + Lfo Frequency Lfo-frekvens + Lfo Amount Lfo-mängd + Output gain Utgångsförstärkning @@ -1003,228 +1233,311 @@ If you're interested in translating LMMS in another language or want to imp DelayControlsDialog - Lfo Amt - + + DELAY + FÖRDRÖJNING + Delay Time Tidsfördröjning - Feedback Amount - Återgivningsmängd - - - Lfo - Lfo - - - Out Gain - Ut-förstärkning - - - Gain - Förstärkning - - - DELAY - - - + FDBK + + Feedback Amount + Återgivningsmängd + + + RATE + HASTIGHET + + + + Lfo + Lfo + + + + AMNT - AMNT + + Lfo Amt + + + Out Gain + Ut-förstärkning + + + + Gain + Förstärkning + DualFilterControlDialog - Filter 1 enabled - Filter 1 aktiverat - - - Filter 2 enabled - Filter 2 aktiverat - - - Click to enable/disable Filter 1 - Klicka för att aktivera/inaktivera Filter 1 - - - Click to enable/disable Filter 2 - Klicka för att aktivera/inaktivera Filter 2 - - + + FREQ FREKV. + + Cutoff frequency Cutoff frekvens + + RESO RESO + + Resonance Resonans + + GAIN FÖRST. + + Gain Förstärkning + MIX MIX + Mix Mix + + + Filter 1 enabled + Filter 1 aktiverat + + + + Filter 2 enabled + Filter 2 aktiverat + + + + Click to enable/disable Filter 1 + Klicka för att aktivera/inaktivera Filter 1 + + + + Click to enable/disable Filter 2 + Klicka för att aktivera/inaktivera Filter 2 + DualFilterControls + Filter 1 enabled Filter 1 aktiverat + Filter 1 type Filter 1 typ + Cutoff 1 frequency Cutoff 1 frekvens + Q/Resonance 1 Q/Resonans 1 + Gain 1 Förstärkning 1 + Mix Mix + Filter 2 enabled Filter 2 aktiverat + Filter 2 type Filter 2 typ + Cutoff 2 frequency Cutoff 2 frekvens + Q/Resonance 2 Q/Resonans 2 + Gain 2 Förstärkning 2 + + LowPass Lågpass + + HiPass Högpass + + BandPass csg - + BandPass csg + + BandPass czpg - + BandPass czpg + + Notch + + Allpass - + Allpass + + Moog Moog + + 2x LowPass 2x Lågpass + + RC LowPass 12dB RC Lågpass 12dB + + RC BandPass 12dB RC BandPass 12dB + + RC HighPass 12dB RC Högpass 12dB + + RC LowPass 24dB RC Lågpass 24dB + + RC BandPass 24dB RC BandPass 24dB + + RC HighPass 24dB RC Högpass 24dB + + Vocal Formant Filter + + 2x Moog - + 2x Moog + + SV LowPass SV Lågpass + + SV BandPass SV BandPass + + SV HighPass SV Högpass + + SV Notch + + Fast Formant + + Tripole @@ -1232,48 +1545,58 @@ If you're interested in translating LMMS in another language or want to imp Editor + + Transport controls + Transportkontroller + + + Play (Space) Play (Mellanslag) + Stop (Space) Stop (Mellanslag) + Record Spela in + Record while playing Spela in under uppspelningen - - Transport controls - Transportkontroller - Effect + Effect enabled Effekt aktiverad + Wet/Dry mix Blöt/Torr mix + Gate - + Gate + Decay - Decay + Förfall EffectChain + Effects enabled Effekter aktiverade @@ -1281,10 +1604,12 @@ If you're interested in translating LMMS in another language or want to imp EffectRackView + EFFECTS CHAIN EFFEKTKEDJA + Add effect Lägg till effekt @@ -1292,22 +1617,28 @@ If you're interested in translating LMMS in another language or want to imp EffectSelectDialog + Add effect Lägg till effekt + + Name Namn + Type Typ + Description Beskrivning + Author Författare @@ -1315,54 +1646,67 @@ If you're interested in translating LMMS in another language or want to imp EffectView + Toggles the effect on or off. Slår på eller av effekten. + On/Off På/Av + W/D - W/D - - - Wet Level: + + Wet Level: + Blöt Nivå: + + + The Wet/Dry knob sets the ratio between the input signal and the effect signal that forms the output. + DECAY - DECAY + + Time: Tid: + The Decay knob controls how many buffers of silence must pass before the plugin stops processing. Smaller values will reduce the CPU overhead but run the risk of clipping the tail on delay and reverb effects. + GATE GATE + Gate: Gate: + The Gate knob controls the signal level that is considered to be 'silence' while deciding when to stop processing signals. + Controls Kontroller + Effect plugins function as a chained series of effects where the signal will be processed from top to bottom. The On/Off switch allows you to bypass a given plugin at any point in time. @@ -1379,73 +1723,90 @@ Right clicking will bring up a context menu where you can change the order in wh + Move &up Flytta &upp + Move &down Flytta &ner + &Remove this plugin - &Ta bort det här insticksprogrammet + &Ta bort den här insticksmodulen EnvelopeAndLfoParameters + Predelay För-fördröjning + Attack Attack + Hold Hold + Decay Decay + Sustain Sustain + Release Release + Modulation Modulering + LFO Predelay + LFO Attack LFO-Attack + LFO speed LFO-hastighet + LFO Modulation LFO-Modulering + LFO Wave Shape LFO-vågform + Freq x 100 Frekv. x 100 + Modulate Env-Amount Modulera Env-mängd @@ -1453,349 +1814,439 @@ Right clicking will bring up a context menu where you can change the order in wh EnvelopeAndLfoView + + DEL - RADERA + RAD + Predelay: För-fördröjning: + Use this knob for setting predelay of the current envelope. The bigger this value the longer the time before start of actual envelope. + + ATT ATT + Attack: Attack: + Use this knob for setting attack-time of the current envelope. The bigger this value the longer the envelope needs to increase to attack-level. Choose a small value for instruments like pianos and a big value for strings. + HOLD HOLD + Hold: Hold: + Use this knob for setting hold-time of the current envelope. The bigger this value the longer the envelope holds attack-level before it begins to decrease to sustain-level. + DEC DEC + Decay: Decay: + Use this knob for setting decay-time of the current envelope. The bigger this value the longer the envelope needs to decrease from attack-level to sustain-level. Choose a small value for instruments like pianos. + SUST SUST + Sustain: Sustain: + Use this knob for setting sustain-level of the current envelope. The bigger this value the higher the level on which the envelope stays before going down to zero. + REL REL + Release: Release: + Use this knob for setting release-time of the current envelope. The bigger this value the longer the envelope needs to decrease from sustain-level to zero. Choose a big value for soft instruments like strings. + + AMT MÄNGD + + Modulation amount: Moduleringsmängd: + Use this knob for setting modulation amount of the current envelope. The bigger this value the more the according size (e.g. volume or cutoff-frequency) will be influenced by this envelope. + LFO predelay: LFO-för-fördröjning: + Use this knob for setting predelay-time of the current LFO. The bigger this value the the time until the LFO starts to oscillate. Använd denna ratt för att ställa för-fördröjningen för aktuell LFO. Ju högre värdet är desto längre tid tar det innan LFO'n börjar oscillera. + LFO- attack: LFO-attack: + Use this knob for setting attack-time of the current LFO. The bigger this value the longer the LFO needs to increase its amplitude to maximum. Använd denna ratt för att ställa attack-tiden för aktuell LFO. Ju högre värdet är desto längre tid tar det för LFO'n att nå sin maximala amplitud. + SPD - + SPD + LFO speed: - + LFO-hastighet: + Use this knob for setting speed of the current LFO. The bigger this value the faster the LFO oscillates and the faster will be your effect. Använd denna ratt för att ställa hastigheten för aktuell LFO. Ju högre värdet är desto snabbare oscillerar LFO'n och desto snabbare är effekten. + Use this knob for setting modulation amount of the current LFO. The bigger this value the more the selected size (e.g. volume or cutoff-frequency) will be influenced by this LFO. Använd denna ratt för att ställa mängden modulering för aktuell LFO. Ju högre värdet är desto större valt värde (volym eller cutoff-frekvens) kommer influeras av denna LFO. + Click here for a sine-wave. Klicka här för sinusvåg. + Click here for a triangle-wave. Klicka här för triangelvåg. + Click here for a saw-wave for current. Klicka här för sågtandsvåg för aktuell. + Click here for a square-wave. - Klicka här för fyrkantvåg + Klicka här för fyrkantvåg. + Click here for a user-defined wave. Afterwards, drag an according sample-file onto the LFO graph. + + Click here for random wave. + Klicka här för en slumpmässig vågform. + + + FREQ x 100 FREKV. x 100 + Click here if the frequency of this LFO should be multiplied by 100. Klicka här för att multiplicera frekvensen för denna LFO med 100. + multiply LFO-frequency by 100 multiplicera LFO-frekvensen med 100 + MODULATE ENV-AMOUNT + Click here to make the envelope-amount controlled by this LFO. + control envelope-amount by this LFO + ms/LFO: ms/LFO: + Hint Ledtråd + Drag a sample from somewhere and drop it in this window. Dra en ljudfil till det här fönstret. - - Click here for random wave. - Klicka här för en slumpmässig vågform. - EqControls + Input gain Ingångsförstärkning + Output gain Utgångsförstärkning + Low shelf gain + Peak 1 gain + Peak 2 gain + Peak 3 gain + Peak 4 gain + High Shelf gain + HP res + Low Shelf res + Peak 1 BW + Peak 2 BW + Peak 3 BW + Peak 4 BW + High Shelf res + LP res + HP freq + Low Shelf freq + Peak 1 freq + Peak 2 freq + Peak 3 freq + Peak 4 freq + High shelf freq + LP freq + HP active + Low shelf active + Peak 1 active + Peak 2 active + Peak 3 active + Peak 4 active + High shelf active + LP active - + LP aktiv + LP 12 - + LP 12 + LP 24 - + LP 24 + LP 48 - + LP 48 + HP 12 - + HP 12 + HP 24 - + HP 24 + HP 48 - + HP 48 + low pass type Lågpass-typ + high pass type Högpass-typ + Analyse IN Analysera IN + Analyse OUT Analysera UT @@ -1803,85 +2254,108 @@ Right clicking will bring up a context menu where you can change the order in wh EqControlsDialog + HP - + HP + Low Shelf + Peak 1 + Peak 2 + Peak 3 + Peak 4 + High Shelf + LP - + LP + In Gain In-förstärkning + + + Gain Förstärkning + Out Gain Ut-förstärkning + Bandwidth: Bandbredd: + + Octave + Oktav + + + Resonance : Resonans: + Frequency: Frekvens: + lp grp + hp grp - - Octave - Oktav - EqHandle + Reso: Reso.: + BW: + + Freq: Frekv.: @@ -1889,174 +2363,243 @@ Right clicking will bring up a context menu where you can change the order in wh ExportProjectDialog + Export project Exportera projekt + Output Utgång + File format: - Fil-format: + Filformat: + Samplerate: Samplingshastighet: + 44100 Hz 44100 Hz + 48000 Hz 48000 Hz + 88200 Hz 88200 Hz + 96000 Hz 96000 Hz + 192000 Hz 192000 Hz - Bitrate: - Bit-hastighet: - - - 64 KBit/s - 64 KBit/s - - - 128 KBit/s - 128 KBit/s - - - 160 KBit/s - 160 KBit/s - - - 192 KBit/s - 192 KBit/s - - - 256 KBit/s - 256 KBit/s - - - 320 KBit/s - 320 KBit/s - - + Depth: Djup: + 16 Bit Integer + + 24 Bit Integer + + + + 32 Bit Float - Please note that not all of the parameters above apply for all file formats. - Alla inställningar ovan gäller för samtliga filformat + + Stereo mode: + Stereoläge: + + Stereo + Stereo + + + + Joint Stereo + + + + + Mono + Mono + + + + Bitrate: + Bithastighet: + + + + 64 KBit/s + 64 KBit/s + + + + 128 KBit/s + 128 KBit/s + + + + 160 KBit/s + 160 KBit/s + + + + 192 KBit/s + 192 KBit/s + + + + 256 KBit/s + 256 KBit/s + + + + 320 KBit/s + 320 KBit/s + + + + Use variable bitrate + Använd variabel bithastighet + + + Quality settings Kvalitetsinställningar + Interpolation: Interpolering: + Zero Order Hold + Sinc Fastest + Sinc Medium (recommended) + Sinc Best (very slow!) + Oversampling (use with care!): Översampling (använd varsamt!): + 1x (None) 1x (Ingen) + 2x 2x + 4x 4x + 8x 8x - Start - Starta - - - Cancel - Avbryt - - + Export as loop (remove end silence) Exportera som loop (ta bort slut-tystnad) + Export between loop markers - Exportera mellan loop-markeringar + Exportera mellan slinga-markeringar + + Start + Starta + + + + Cancel + Avbryt + + + Could not open file Kunde inte öppna fil + + Could not open file %1 for writing. +Please make sure you have write permission to the file and the directory containing the file and try again! + Det gick inte att öppna filen %1 för att skriva. +Se till att du har skrivbehörighet till filen och mappen som innehåller filen och försök igen! + + + Export project to %1 Exportera projekt till %1 + Error Fel + Error while determining file-encoder device. Please try to choose a different output format. - + Fel vid bestämning av filkodarenhet. Vänligen försök att välja ett annat utmatningsformat. + Rendering: %1% Renderar: %1% - - Could not open file %1 for writing. -Please make sure you have write permission to the file and the directory containing the file and try again! - - Fader + + Please enter a new value between %1 and %2: Ange ett nytt värde mellan %1 och %2: @@ -2064,72 +2607,88 @@ Please make sure you have write permission to the file and the directory contain FileBrowser + Browser - + Bläddrare FileBrowserTreeWidget + Send to active instrument-track Skicka till aktivt instrument-spår + + Open in new instrument-track/Song Editor + Öppna i nytt instrument-spår/Låt-redigeraren + + + Open in new instrument-track/B+B Editor + Loading sample - Laddar ljudfil + Läser in ljudfil + Please wait, loading sample for preview... - Ljudfilen laddas för förhandslyssning... - - - --- Factory files --- - --- Grundfiler --- - - - Open in new instrument-track/Song Editor - Öppna i nytt instrument-spår/Sång Editor + Ljudfilen läses in för förhandslyssning... + Error Fel + does not appear to be a valid verkar inte vara en giltig + file fil + + + --- Factory files --- + --- Grundfiler --- + FlangerControls + Delay Samples - Fördröj Samplingar + Fördröj samplingar + Lfo Frequency Lfo-frekvens + Seconds Sekunder + Regen + Noise Brus + Invert Invertera @@ -2137,46 +2696,57 @@ Please make sure you have write permission to the file and the directory contain FlangerControlsDialog - Delay Time: - - - - Feedback Amount: - - - - White Noise Amount: - - - + DELAY - + FÖRDRÖJNING + + Delay Time: + Fördröjningstid: + + + RATE - + HASTIGHET - Rate: - + + Period: + Period: + AMNT + Amount: - + Mängd: + FDBK - NOISE + + Feedback Amount: + + NOISE + BRUS + + + + White Noise Amount: + + + + Invert Invertera @@ -2184,10 +2754,12 @@ Please make sure you have write permission to the file and the directory contain FxLine + Channel send amount - + Kanalsändningsbelopp + The FX channel receives input from one or more instrument tracks. It in turn can be routed to multiple other FX channels. LMMS automatically takes care of preventing infinite loops for you and doesn't allow making a connection that would result in an infinite loop. @@ -2198,22 +2770,27 @@ You can remove and move FX channels in the context menu, which is accessed by ri + Move &left Flytta &vänster + Move &right Flytta &höger + Rename &channel Byt namn på &kanal + R&emove channel T&a bort kanal + Remove &unused channels Ta bort &oanvända kanaler @@ -2221,37 +2798,62 @@ You can remove and move FX channels in the context menu, which is accessed by ri FxMixer + Master Master + + + FX %1 FX %1 + + + Volume + Volym + + + + Mute + Tysta + + + + Solo + Solo + FxMixerView + FX-Mixer FX-Mixer + FX Fader %1 FX Fader %1 + Mute Tysta + Mute this FX channel Tysta denna FX-kanal + Solo Solo + Solo FX channel FX-kanal Solo @@ -2259,6 +2861,8 @@ You can remove and move FX channels in the context menu, which is accessed by ri FxRoute + + Amount to send from channel %1 to channel %2 Mängd att skicka från kanal %1 till kanal %2 @@ -2266,14 +2870,17 @@ You can remove and move FX channels in the context menu, which is accessed by ri GigInstrument + Bank Bank + Patch + Gain Förstärkning @@ -2281,46 +2888,58 @@ You can remove and move FX channels in the context menu, which is accessed by ri GigInstrumentView + Open other GIG file Öppna en annan GIG-fil + Click here to open another GIG file Klicka här för att öppna en annan GIG-fil + Choose the patch + Click here to change which patch of the GIG file to use + + Change which instrument of the GIG file is being played Välj vilket instrument i GIG-filen som ska spelas + Which GIG file is currently being used Vilken GIG-fil används för närvarande + Which patch of the GIG file is currently being used Vilken del av GIG-filen används för närvarande + Gain Förstärkning + Factor to multiply samples by Faktor att multiplicera samplingar med + Open GIG file Öppna GIG-fil + GIG Files (*.gig) GIG-filer (*.gig) @@ -2328,704 +2947,880 @@ You can remove and move FX channels in the context menu, which is accessed by ri GuiApplication + Working directory - Arbetskatalog + Arbetsmapp + The LMMS working directory %1 does not exist. Create it now? You can change the directory later via Edit -> Settings. - Arbetskatalogen %1 för LMMS existerar inte. Vill du skapa detta nu? Du kan ändra katalog senare under Redigera -> Inställningar. + Arbetsmappen %1 för LMMS finns inte. Vill du skapa denna nu? Du kan ändra mappen senare via Redigera -> Inställningar. + Preparing UI Förbereder användargränssnitt + Preparing song editor - Förbereder sång-editor + Förbereder låtredigeraren + Preparing mixer Förbereder mixer + Preparing controller rack Förbereder kontrollrack + Preparing project notes Förbereder projektanteckningar + Preparing beat/bassline editor - Förbereder Takt/Bas-editor + Förbereder takt/basgång-redigeraren + Preparing piano roll Förbereder pianorulle + Preparing automation editor - Förbereder automations-editor + Förbereder automationsredigeraren InstrumentFunctionArpeggio + Arpeggio Arpeggio + Arpeggio type Arpeggio-typ + Arpeggio range Arpeggio-omfång - Arpeggio time - Arpeggio-tid - - - Arpeggio gate + + Cycle steps - Arpeggio direction - Arpeggio-riktning - - - Arpeggio mode - Arpeggio-typ - - - Up - Upp - - - Down - Ner - - - Up and down - Upp och ner - - - Random - Slumpmässig - - - Free - - - - Sort - - - - Sync - - - - Down and up - Ner och upp - - + Skip rate + Miss rate - Cycle steps + + Arpeggio time + Arpeggio-tid + + + + Arpeggio gate + + + Arpeggio direction + Arpeggio-riktning + + + + Arpeggio mode + Arpeggio-typ + + + + Up + Upp + + + + Down + Ner + + + + Up and down + Upp och ner + + + + Down and up + Ner och upp + + + + Random + Slumpmässig + + + + Free + Fritt + + + + Sort + Sortera + + + + Sync + Synkronisera + InstrumentFunctionArpeggioView + ARPEGGIO ARPEGGIO + An arpeggio is a method playing (especially plucked) instruments, which makes the music much livelier. The strings of such instruments (e.g. harps) are plucked like chords. The only difference is that this is done in a sequential order, so the notes are not played at the same time. Typical arpeggios are major or minor triads, but there are a lot of other possible chords, you can select. + RANGE OMFÅNG + Arpeggio range: Arpeggio-omfång: + octave(s) oktav(er) + Use this knob for setting the arpeggio range in octaves. The selected arpeggio will be played within specified number of octaves. - TIME - TID - - - Arpeggio time: - Arpeggio-tid: - - - ms - ms - - - Use this knob for setting the arpeggio time in milliseconds. The arpeggio time specifies how long each arpeggio-tone should be played. - Använd denna ratt för att ställa arpeggio-tiden i millisekunder. Arpeggio-tiden anger hur länge varje arpeggio-ton ska spelas. - - - GATE - GATE - - - Arpeggio gate: - - - - % - % - - - Use this knob for setting the arpeggio gate. The arpeggio gate specifies the percent of a whole arpeggio-tone that should be played. With this you can make cool staccato arpeggios. - - - - Chord: - Ackord: - - - Direction: - Riktning: - - - Mode: - Läge: - - - SKIP - - - - Skip rate: - - - - The skip function will make the arpeggiator pause one step randomly. From its start in full counter clockwise position and no effect it will gradually progress to full amnesia at maximum setting. - - - - MISS - - - - Miss rate: - - - - The miss function will make the arpeggiator miss the intended note. - - - + CYCLE + Cycle notes: + note(s) not(er) + Jumps over n steps in the arpeggio and cycles around if we're over the note range. If the total note range is evenly divisible by the number of steps jumped over you will get stuck in a shorter arpeggio or even on one note. + + + SKIP + + + + + Skip rate: + + + + + + + % + % + + + + The skip function will make the arpeggiator pause one step randomly. From its start in full counter clockwise position and no effect it will gradually progress to full amnesia at maximum setting. + + + + + MISS + + + + + Miss rate: + + + + + The miss function will make the arpeggiator miss the intended note. + + + + + TIME + TID + + + + Arpeggio time: + Arpeggio-tid: + + + + ms + ms + + + + Use this knob for setting the arpeggio time in milliseconds. The arpeggio time specifies how long each arpeggio-tone should be played. + Använd denna ratt för att ställa arpeggio-tiden i millisekunder. Arpeggio-tiden anger hur länge varje arpeggio-ton ska spelas. + + + + GATE + GATE + + + + Arpeggio gate: + + + + + Use this knob for setting the arpeggio gate. The arpeggio gate specifies the percent of a whole arpeggio-tone that should be played. With this you can make cool staccato arpeggios. + + + + + Chord: + Ackord: + + + + Direction: + Riktning: + + + + Mode: + Läge: + InstrumentFunctionNoteStacking + octave oktav + + Major - + Dur + Majb5 + minor - + moll + minb5 + sus2 + sus4 + aug + augsus4 + tri + 6 - + 6 + 6sus4 + 6add9 + m6 + m6add9 + 7 - + 7 + 7sus4 + 7#5 - + 7#5 + 7b5 - + 7b5 + 7#9 - + 7#9 + 7b9 - + 7b9 + 7#5#9 - + 7#5#9 + 7#5b9 - + 7#5b9 + 7b5b9 - + 7b5b9 + 7add11 + 7add13 + 7#11 - + 7#11 + Maj7 + Maj7b5 + Maj7#5 + Maj7#11 + Maj7add13 + m7 + m7b5 + m7b9 + m7add11 + m7add13 + m-Maj7 + m-Maj7add11 + m-Maj7add13 + 9 - + 9 + 9sus4 + add9 + 9#5 - + 9#5 + 9b5 - + 9b5 + 9#11 - + 9#11 + 9b13 - + 9b13 + Maj9 + Maj9sus4 + Maj9#5 + Maj9#11 + m9 + madd9 + m9b5 + m9-Maj7 + 11 - + 11 + 11b9 + Maj11 + m11 + m-Maj11 + 13 - + 13 + 13#9 - + 13#9 + 13b9 - + 13b9 + 13b5b9 - + 13b5b9 + Maj13 + m13 + m-Maj13 + Harmonic minor - + Harmonisk moll + Melodic minor - + Melodisk moll + Whole tone - + Hela tonen + Diminished - + Minskad + Major pentatonic + Minor pentatonic + Jap in sen + Major bebop + Dominant bebop + Blues - + Blues + Arabic - + Arabisk + Enigmatic - + Gåtfull + Neopolitan + Neopolitan minor + Hungarian minor + Dorian - Phrygolydian + + Phrygian + Lydian + Mixolydian + Aeolian + Locrian - Chords - Ackord - - - Chord type - Ackord-typ - - - Chord range - - - + Minor - + Moll + Chromatic - + Kromatisk + Half-Whole Diminished + 5 - + 5 + Phrygian dominant + Persian - + Persisk + + + + Chords + Ackord + + + + Chord type + Ackordtyp + + + + Chord range + Ackordomfång InstrumentFunctionNoteStackingView + + STACKING + STAPLA + + + + Chord: + Ackord: + + + RANGE OMFÅNG + Chord range: - + Ackordomfång: + octave(s) oktav(er) + Use this knob for setting the chord range in octaves. The selected chord will be played within specified number of octaves. - - STACKING - - - - Chord: - Ackord: - InstrumentMidiIOView + ENABLE MIDI INPUT AKTIVERA MIDI-INMATNING + + CHANNEL KANAL + + VELOCITY - + HASTIGHET + ENABLE MIDI OUTPUT - + AKTIVERA MIDI-UTGÅNG + PROGRAM - - - - MIDI devices to receive MIDI events from - - - - MIDI devices to send MIDI events to - + PROGRAM + NOTE - + NOT + + MIDI devices to receive MIDI events from + MIDI-enheter att ta emot MIDI-händelser från + + + + MIDI devices to send MIDI events to + MIDI-enheter att skicka MIDI-händelser till + + + CUSTOM BASE VELOCITY - + ANPASSAD BASHASTIGHET + Specify the velocity normalization base for MIDI-based instruments at 100% note velocity + BASE VELOCITY - + BASHASTIGHET InstrumentMiscView + MASTER PITCH + Enables the use of Master Pitch @@ -3033,126 +3828,158 @@ You can remove and move FX channels in the context menu, which is accessed by ri InstrumentSoundShaping + VOLUME VOLYM + Volume Volym + CUTOFF + + Cutoff frequency Cutoff frekvens + RESO RESO + Resonance Resonans + Envelopes/LFOs + Filter type Filtertyp + Q/Resonance Q/Resonans + LowPass Lågpass + HiPass Högpass + BandPass csg - + BandPass csg + BandPass czpg - + BandPass czpg + Notch + Allpass - + Allpass + Moog Moog + 2x LowPass 2x Lågpass + RC LowPass 12dB RC Lågpass 12dB + RC BandPass 12dB RC BandPass 12dB + RC HighPass 12dB RC Högpass 12dB + RC LowPass 24dB RC Lågpass 24dB + RC BandPass 24dB RC BandPass 24dB + RC HighPass 24dB RC Högpass 24dB + Vocal Formant Filter + 2x Moog - + 2x Moog + SV LowPass SV Lågpass + SV BandPass SV BandPass + SV HighPass SV Högpass + SV Notch + Fast Formant + Tripole @@ -3160,50 +3987,62 @@ You can remove and move FX channels in the context menu, which is accessed by ri InstrumentSoundShapingView + TARGET MÅL + These tabs contain envelopes. They're very important for modifying a sound, in that they are almost always necessary for substractive synthesis. For example if you have a volume envelope, you can set when the sound should have a specific volume. If you want to create some soft strings then your sound has to fade in and out very softly. This can be done by setting large attack and release times. It's the same for other envelope targets like panning, cutoff frequency for the used filter and so on. Just monkey around with it! You can really make cool sounds out of a saw-wave with just some envelopes...! + FILTER FILTER + Here you can select the built-in filter you want to use for this instrument-track. Filters are very important for changing the characteristics of a sound. Här kan du välja vilket inbyggt filter du vill använda för detta instrument-spår. Filter är väldigt viktiga om man vill ändra karaktäristiken på ett ljud. - Hz - Hz - - - Use this knob for setting the cutoff frequency for the selected filter. The cutoff frequency specifies the frequency for cutting the signal by a filter. For example a lowpass-filter cuts all frequencies above the cutoff frequency. A highpass-filter cuts all frequencies below cutoff frequency, and so on... - - - - RESO - RESO - - - Resonance: - Resonans: - - - Use this knob for setting Q/Resonance for the selected filter. Q/Resonance tells the filter how much it should amplify frequencies near Cutoff-frequency. - - - + FREQ FREKV. + cutoff frequency: cutoff-frekvens: + + Hz + Hz + + + + Use this knob for setting the cutoff frequency for the selected filter. The cutoff frequency specifies the frequency for cutting the signal by a filter. For example a lowpass-filter cuts all frequencies above the cutoff frequency. A highpass-filter cuts all frequencies below cutoff frequency, and so on... + + + + + RESO + RESO + + + + Resonance: + Resonans: + + + + Use this knob for setting Q/Resonance for the selected filter. Q/Resonance tells the filter how much it should amplify frequencies near Cutoff-frequency. + + + + Envelopes, LFOs and filters are not supported by the current instrument. @@ -3211,85 +4050,107 @@ You can remove and move FX channels in the context menu, which is accessed by ri InstrumentTrack - unnamed_track - namnlöst_spår - - - Volume - Volym - - - Panning - Panorering - - - Pitch - Tonhöjd - - - FX channel - FX-kanal - - - Default preset - Standardinställning - - + With this knob you can set the volume of the opened channel. Med denna ratt ställer du volymen för den öppnade kanalen. + + + unnamed_track + namnlöst_spår + + + Base note Grundton + + Volume + Volym + + + + Panning + Panorering + + + + Pitch + Tonhöjd + + + Pitch range Tonhöjdsomfång + + FX channel + FX-kanal + + + Master Pitch + + + + Default preset + Standardinställning + InstrumentTrackView + Volume Volym + Volume: Volym: + VOL VOL + Panning Panorering + Panning: Panorering: + PAN - PANORERA + PAN + MIDI MIDI + Input Ingång + Output Utgång + FX %1: %2 FX %1: %2 @@ -3297,125 +4158,160 @@ You can remove and move FX channels in the context menu, which is accessed by ri InstrumentTrackWindow + GENERAL SETTINGS ÖVERGRIPANDE INSTÄLLNINGAR + + Use these controls to view and edit the next/previous track in the song editor. + Använd dessa kontroller för att visa och redigera nästa/föregående spår i låtredigeraren. + + + Instrument volume Instrument-volym + Volume: Volym: + VOL VOL + Panning Panorering + Panning: Panorering: + PAN - PANORERA + PAN + Pitch Tonhöjd + Pitch: Tonhöjd: + cents + PITCH - FX channel - FX-kanal - - - ENV/LFO - - - - FUNC - - - - FX - - - - MIDI - MIDI - - - Save preset - Spara förinställning - - - XML preset file (*.xpf) - XML förinställnings-fil (*.xpf) - - - PLUGIN - - - + Pitch range (semitones) + RANGE OMFÅNG - Save current instrument track settings in a preset file - + + FX channel + FX-kanal + + FX + FX + + + + Save current instrument track settings in a preset file + Spara aktuella instrumentspårinställningar i en förinställd fil + + + Click here, if you want to save current instrument track settings in a preset file. Later you can load this preset by double-clicking it in the preset-browser. - MISC - - - - Use these controls to view and edit the next/previous track in the song editor. - - - + SAVE SPARA + + + Envelope, filter & LFO + + + + + Chord stacking & arpeggio + + + + + Effects + Effekter + + + + MIDI settings + MIDI-inställningar + + + + Miscellaneous + Diverse + + + + Save preset + Spara förinställning + + + + XML preset file (*.xpf) + XML förinställnings-fil (*.xpf) + + + + Plugin + Insticksmodul + Knob + Set linear - + Ställ in linjär + Set logarithmic - + Ställ in logaritmisk + Please enter a new value between -96.0 dBFS and 6.0 dBFS: - + Vänligen ange ett nytt värde mellan -96.0 dBFS och 6.0 dBFS: + Please enter a new value between %1 and %2: Ange ett nytt värde mellan %1 och %2: @@ -3423,6 +4319,7 @@ You can remove and move FX channels in the context menu, which is accessed by ri LadspaControl + Link channels Länka kanaler @@ -3430,10 +4327,12 @@ You can remove and move FX channels in the context menu, which is accessed by ri LadspaControlDialog + Link Channels Länka Kanaler + Channel Kanal @@ -3441,14 +4340,17 @@ You can remove and move FX channels in the context menu, which is accessed by ri LadspaControlView + Link channels Länka kanaler + Value: Värde: + Sorry, no help available. Ledsen, ingen hjälp är tillgänglig. @@ -3456,13 +4358,15 @@ You can remove and move FX channels in the context menu, which is accessed by ri LadspaEffect + Unknown LADSPA plugin %1 requested. - + Okänd LADSPA-insticksmodul %1 efterfrågad. LcdSpinBox + Please enter a new value between %1 and %2: Ange ett nytt värde mellan %1 och %2: @@ -3470,18 +4374,26 @@ You can remove and move FX channels in the context menu, which is accessed by ri LeftRightNav + + + Previous Tidigare + + + Next Nästa + Previous (%1) Tidigare (%1) + Next (%1) Nästa (%1) @@ -3489,145 +4401,180 @@ You can remove and move FX channels in the context menu, which is accessed by ri LfoController + LFO Controller + Base value Basvärde + Oscillator speed - + Oscillatorhastighet + Oscillator amount - + Oscillatormängd + Oscillator phase - + Oscillatorfas + Oscillator waveform - + Oscillatorvågform + Frequency Multiplier - + Frekvens Multiplikator LfoControllerDialog + LFO LFO + LFO Controller + BASE + Base amount: + todo + SPD - + SPD + LFO-speed: + Use this knob for setting speed of the LFO. The bigger this value the faster the LFO oscillates and the faster the effect. + + AMNT + + + + Modulation amount: Moduleringsmängd: + Use this knob for setting modulation amount of the LFO. The bigger this value, the more the connected control (e.g. volume or cutoff-frequency) will be influenced by the LFO. + PHS + Phase offset: + degrees grader + With this knob you can set the phase offset of the LFO. That means you can move the point within an oscillation where the oscillator begins to oscillate. For example if you have a sine-wave and have a phase-offset of 180 degrees the wave will first go down. It's the same with a square-wave. + Click here for a sine-wave. Klicka här för sinusvåg. + Click here for a triangle-wave. Klicka här för triangelvåg. + Click here for a saw-wave. - Klicka här för sågtandvåg + Klicka här för sågtandsvåg + Click here for a square-wave. - Klicka här för fyrkantvåg - - - Click here for an exponential wave. - - - - Click here for white-noise. - Klicka här för vitt brus. - - - Click here for a user-defined shape. -Double click to pick a file. - + Klicka här för fyrkantvåg. + Click here for a moog saw-wave. - AMNT + + Click here for an exponential wave. + + + Click here for white-noise. + Klicka här för vitt brus. + + + + Click here for a user-defined shape. +Double click to pick a file. + Klicka här för en användardefinierad form. +Dubbelklicka för att välja en fil. + LmmsCore + Generating wavetables + Initializing data structures - + Initierar datastrukturer + Opening audio and midi devices - + Öppnar ljud- och midienheter + Launching mixer threads @@ -3635,404 +4582,500 @@ Double click to pick a file. MainWindow - Could not save config-file - + + Configuration file + Konfigurationsfil - Could not save configuration file %1. You're probably not permitted to write to this file. -Please make sure you have write-access to the file and try again. - + + Error while parsing configuration file at line %1:%2: %3 + Fel vid inläsning av konfigurationsfil på rad %1:%2: %3 + + Could not open file + Kunde inte öppna fil + + + + Could not open file %1 for writing. +Please make sure you have write permission to the file and the directory containing the file and try again! + Det gick inte att öppna filen %1 för att skriva. +Se till att du har skrivbehörighet till filen och mappen som innehåller filen och försök igen! + + + + Project recovery + Projektåterställning + + + + There is a recovery file present. It looks like the last session did not end properly or another instance of LMMS is already running. Do you want to recover the project of this session? + Det finns en återställningsfil tillgänglig. Det verkar som om programmet inte avslutades korrekt senast, eller så körs redan LMMS. Vill du återställa detta projekt? + + + + + + Recover + Återställ + + + + Recover the file. Please don't run multiple instances of LMMS when you do this. + Återställ filen. Se till att du bara har en instans av LMMS igång när du gör detta. + + + + + + Discard + Kasta bort + + + + Launch a default session and delete the restored files. This is not reversible. + Starta en standard-session och ta bort den återskapade filen. Detta går inte ångra. + + + + Version %1 + Version %1 + + + + Preparing plugin browser + Förbereder insticksmodulsbläddraren + + + + Preparing file browsers + Förbereder fil-browser + + + + My Projects + Mina projekt + + + + My Samples + Mina samplingar + + + + My Presets + Mina förinställningar + + + + My Home + Min hemmapp + + + + Root directory + Rotmapp + + + + Volumes + Volymer + + + + My Computer + Min dator + + + + Loading background artwork + Laddar bakgrunds-grafik + + + + &File + &Arkiv + + + &New &Ny + + New from template + Nytt från mall + + + &Open... &Öppna... + + &Recently Opened Projects + &Nyligen öppnade projekt + + + &Save &Spara + Save &As... Spara &som... + + Save as New &Version + Spara som ny &version + + + + Save as default template + Spara som standardmall + + + Import... Importera... + E&xport... E&xportera... + + E&xport Tracks... + E&xportera spår... + + + + Export &MIDI... + Exportera &MIDI... + + + &Quit &Avsluta + &Edit &Redigera + + Undo + Ångra + + + + Redo + Gör om + + + Settings Inställningar - &Tools - + + &View + &Visa + + &Tools + &Verktyg + + + &Help &Hjälp + + Online Help + Hjälp på nätet + + + Help Hjälp - What's this? - Vad är detta? + + What's This? + Vad är det här? + About Om + Create new project Skapa nytt projekt + Create new project from template Skapa nytt projekt från mall + Open existing project Öppna existerande projekt + Recently opened projects Nyligen öppnade projekt + Save current project Spara aktuellt projekt + Export current project Exportera aktuellt projekt - Song Editor - Sång-editor + + What's this? + Vad är detta? + + Toggle metronome + Slå på/av metronom + + + + Show/hide Song-Editor + Visa/dölj Låtredigeraren + + + By pressing this button, you can show or hide the Song-Editor. With the help of the Song-Editor you can edit song-playlist and specify when which track should be played. You can also insert and move samples (e.g. rap samples) directly into the playlist. - + Genom att trycka på den här knappen kan du visa eller dölja Låtredigeraren. Med hjälp av Låtredigeraren kan du redigera låtspellista och ange när vilken låt ska spelas. Du kan också infoga och flytta samplingar (t.ex. rap-samplingar) direkt i spellistan. - Beat+Bassline Editor - Redigera Trummor+Bas + + Show/hide Beat+Bassline Editor + Visa/dölj Takt+Basgång-redigeraren + By pressing this button, you can show or hide the Beat+Bassline Editor. The Beat+Bassline Editor is needed for creating beats, and for opening, adding, and removing channels, and for cutting, copying and pasting beat and bassline-patterns, and for other things like that. - Piano Roll - Pianorulle + + Show/hide Piano-Roll + Visa/dölj pianorulle + Click here to show or hide the Piano-Roll. With the help of the Piano-Roll you can edit melodies in an easy way. Klicka här för att visa eller dölja pianorullen. Med hjälp av pianorullen kan du skapa melodier på ett enkelt sätt. - Automation Editor - Automations-editor + + Show/hide Automation Editor + Visa/dölj Automationsredigeraren + Click here to show or hide the Automation Editor. With the help of the Automation Editor you can edit dynamic values in an easy way. - FX Mixer - + + Show/hide FX Mixer + Visa/dölj FX Mixer + Click here to show or hide the FX Mixer. The FX Mixer is a very powerful tool for managing effects for your song. You can insert effects into different effect-channels. - Project Notes - Projektanteckningar + + Show/hide project notes + Visa/dölj projektanteckningar + Click here to show or hide the project notes window. In this window you can put down your project notes. Klicka här för att visa eller dölja fönstret för projektanteckningar. I detta fönster kan du göra noteringar om ditt projekt, - Controller Rack - Kontrollrack + + Show/hide controller rack + Visa/dölj kontrollrack + Untitled Namnlös + + Recover session. Please save your work! + Återställnings-session. Spara ditt arbete! + + + LMMS %1 LMMS %1 - Project not saved - Projekt inte sparat + + Recovered project not saved + Återställt projekt inte sparat + + This project was recovered from the previous session. It is currently unsaved and will be lost if you don't save it. Do you want to save it now? + Projektet återställdes från den senaste sessionen. Det kommer försvinna om du inte sparar det. Vill du spara projektet nu? + + + + Project not saved + Projektet inte sparat + + + The current project was modified since last saving. Do you want to save it now? Projektet har ändrats sedan det sparades senast. Vill du spara nu? + + Open Project + Öppna projekt + + + + LMMS (*.mmp *.mmpz) + LMMS (*.mmp *.mmpz) + + + + Save Project + Spara projekt + + + + LMMS Project + LMMS-Projekt + + + + LMMS Project Template + LMMS-Projektmall + + + + Save project template + Spara projektmall + + + + Overwrite default template? + Vill du skriva över standardmallen? + + + + This will overwrite your current default template. + Detta kommer skriva över din nuvarande standardmall. + + + Help not available Hjälp inte tillgänglig + Currently there's no help available in LMMS. Please visit http://lmms.sf.net/wiki for documentation on LMMS. Just nu finns ingen hjälp tillgänglig i LMMS Besök https://lmms.io/documentation/ för dokumentation (Engelska). - LMMS (*.mmp *.mmpz) - + + Song Editor + Låtredigeraren - Version %1 - Version %1 + + Beat+Bassline Editor + Takt+Basgång-redigeraren - Configuration file - Konfigurationsfil + + Piano Roll + Pianorulle - Error while parsing configuration file at line %1:%2: %3 - Fel vid inläsning av konfigurationsfil på rad %1:%2: %3 + + Automation Editor + Automatiseringsredigeraren - Volumes - + + FX Mixer + FX-mixer - Undo - Ångra + + Project Notes + Projektanteckningar - Redo - Gör om - - - My Projects - Mina Projekt - - - My Samples - - - - My Presets - - - - My Home - - - - My Computer - Min dator - - - &File - &Fil - - - &Recently Opened Projects - &Nyligen öppnade projekt - - - Save as New &Version - Spara som Ny &Version - - - E&xport Tracks... - E&xportera spår... - - - Online Help - Online-hjälp - - - What's This? - Vad är det här? - - - Open Project - Öppna Projekt - - - Save Project - Spara Projekt - - - Project recovery - Projektåterställning - - - There is a recovery file present. It looks like the last session did not end properly or another instance of LMMS is already running. Do you want to recover the project of this session? - Det finns en återställningsfil tillgänglig. Det verkar som om programmet inte avslutades korrekt senast, eller så körs redan LMMS. Vill du återställa detta projekt? - - - Recover - Återställ - - - Recover the file. Please don't run multiple instances of LMMS when you do this. - Återställ filen. Se till att du bara har en instans av LMMS igång när du gör detta. - - - Ignore - Ignorera - - - Launch LMMS as usual but with automatic backup disabled to prevent the present recover file from being overwritten. - Starta LMMS som vanligt men med automatisk backup avstängt för att förhindra att den nuvarande återställningsfilen blir överskriven. - - - Discard - Kasta bort - - - Launch a default session and delete the restored files. This is not reversible. - Starta en standard-session och ta bort den återskapade filen. Detta går inte ångra. - - - Preparing plugin browser - Förbereder plugin-browser - - - Preparing file browsers - Förbereder fil-browser - - - Root directory - Rotkatalog - - - Loading background artwork - Laddar bakgrunds-grafik - - - New from template - Nytt från mall - - - Save as default template - Spara som standard-mall - - - &View - %Visa - - - Toggle metronome - Slå på/av metronom - - - Show/hide Song-Editor - Visa/dölj Sång-editor - - - Show/hide Beat+Bassline Editor - Visa/dölj Takt+Bas-editor - - - Show/hide Piano-Roll - Visa/dölj pianorulle - - - Show/hide Automation Editor - Visa/dölj Automations-editor - - - Show/hide FX Mixer - Visa/dölj FX Mixer - - - Show/hide project notes - Visa/dölj projektanteckningar - - - Show/hide controller rack - Visa/dölj kontrollrack - - - Recover session. Please save your work! - Återställnings-session. Spara ditt arbete! - - - Automatic backup disabled. Remember to save your work! - Automatisk backup avstängd. Kom ihåg att spara ditt arbete! - - - Recovered project not saved - Återställt projekt inte sparat - - - This project was recovered from the previous session. It is currently unsaved and will be lost if you don't save it. Do you want to save it now? - Projektet återställdes från den senaste sessionen. Det kommer försvinna om du inte sparar det. Vill du spara projektet nu? - - - LMMS Project - LMMS-Projekt - - - LMMS Project Template - LMMS-Projektmall - - - Overwrite default template? - Vill du skriva över standardmallen? - - - This will overwrite your current default template. - Detta kommer skriva över din nuvarande standardmall. + + Controller Rack + Kontrollrack + Volume as dBFS Volym som dBFS + Smooth scroll Mjuk rullning + Enable note labels in piano roll Visa noter i pianorulle - - Save project template - - MeterDialog + + Meter Numerator + + Meter Denominator + TIME SIG @@ -4040,107 +5083,130 @@ Besök https://lmms.io/documentation/ för dokumentation (Engelska). MeterModel + Numerator - + Täljare + Denominator - + Nämnare MidiController + MIDI Controller - + MIDI-styrenhet + unnamed_midi_controller - + unnamed_midi_controller MidiImport + + Setup incomplete Installation ofullständig + You do not have set up a default soundfont in the settings dialog (Edit->Settings). Therefore no sound will be played back after importing this MIDI file. You should download a General MIDI soundfont, specify it in settings dialog and try again. - + Du har inte ställt in en standard soundfont i inställningsdialogrutan (Redigera->Inställningar). Därför spelas inget ljud upp efter att ha importerat denna MIDI-fil. Du bör hämta en allmän MIDI-soundfont, ange den i inställningsdialogrutan och försök igen. + You did not compile LMMS with support for SoundFont2 player, which is used to add default sound to imported MIDI files. Therefore no sound will be played back after importing this MIDI file. - + Du kompilerade inte LMMS med stöd för SoundFont2-spelaren, som används för att lägga till standardljud till importerade MIDI-filer. Därför spelas inget ljud upp efter att ha importerat denna MIDI-fil. + Track - + Spår MidiJack + JACK server down When JACK(JACK Audio Connection Kit) disconnects, it will show the following message (title) - JACK server nerstängd + JACK-server nerstängd + The JACK server seems to be shuted down. When JACK(JACK Audio Connection Kit) disconnects, it will show the following message (dialog message) - + JACK-servern verkar vara avstängd. MidiPort + Input channel Ingångskanal + Output channel Utgångskanal + Input controller Ingångskontroller + Output controller Utgångskontroller + Fixed input velocity - + Fast ingångshastighet + Fixed output velocity - + Fast utgångshastighet + + Fixed output note + Fast utgångsnot + + + Output MIDI program - + Utgång MIDI-program + + Base velocity + Bashastighet + + + Receive MIDI-events Ta emot MIDI-event + Send MIDI-events Skicka MIDI-event - - Fixed output note - Fast utgångs-not - - - Base velocity - - MidiSetupWidget + DEVICE ENHET @@ -4148,495 +5214,620 @@ Besök https://lmms.io/documentation/ för dokumentation (Engelska). MonstroInstrument + Osc 1 Volume Osc 1 Volym + Osc 1 Panning Osc 1 Panorering + Osc 1 Coarse detune + Osc 1 Fine detune left + Osc 1 Fine detune right + Osc 1 Stereo phase offset + Osc 1 Pulse width + Osc 1 Sync send on rise + Osc 1 Sync send on fall + Osc 2 Volume + Osc 2 Panning + Osc 2 Coarse detune + Osc 2 Fine detune left + Osc 2 Fine detune right + Osc 2 Stereo phase offset + Osc 2 Waveform + Osc 2 Sync Hard + Osc 2 Sync Reverse + Osc 3 Volume + Osc 3 Panning + Osc 3 Coarse detune + Osc 3 Stereo phase offset + Osc 3 Sub-oscillator mix + Osc 3 Waveform 1 + Osc 3 Waveform 2 + Osc 3 Sync Hard + Osc 3 Sync Reverse + LFO 1 Waveform + LFO 1 Attack + LFO 1 Rate + LFO 1 Phase + LFO 2 Waveform + LFO 2 Attack + LFO 2 Rate + LFO 2 Phase + Env 1 Pre-delay + Env 1 Attack + Env 1 Hold + Env 1 Decay + Env 1 Sustain + Env 1 Release + Env 1 Slope + Env 2 Pre-delay + Env 2 Attack + Env 2 Hold + Env 2 Decay + Env 2 Sustain + Env 2 Release + Env 2 Slope + Osc2-3 modulation + Selected view Vald vy + Vol1-Env1 + Vol1-Env2 + Vol1-LFO1 + Vol1-LFO2 + Vol2-Env1 + Vol2-Env2 + Vol2-LFO1 + Vol2-LFO2 + Vol3-Env1 + Vol3-Env2 + Vol3-LFO1 + Vol3-LFO2 + Phs1-Env1 + Phs1-Env2 + Phs1-LFO1 + Phs1-LFO2 + Phs2-Env1 + Phs2-Env2 + Phs2-LFO1 + Phs2-LFO2 + Phs3-Env1 + Phs3-Env2 + Phs3-LFO1 + Phs3-LFO2 + Pit1-Env1 + Pit1-Env2 + Pit1-LFO1 + Pit1-LFO2 + Pit2-Env1 + Pit2-Env2 + Pit2-LFO1 + Pit2-LFO2 + Pit3-Env1 + Pit3-Env2 + Pit3-LFO1 + Pit3-LFO2 + PW1-Env1 + PW1-Env2 + PW1-LFO1 + PW1-LFO2 + Sub3-Env1 + Sub3-Env2 + Sub3-LFO1 + Sub3-LFO2 + + Sine wave Sinusvåg + Bandlimited Triangle wave + Bandlimited Saw wave + Bandlimited Ramp wave + Bandlimited Square wave + Bandlimited Moog saw wave + + Soft square wave - + Mjuk fyrkantvåg + Absolute sine wave - + Absolut sinusvåg + + Exponential wave - + Exponentiell våg + White noise - + Vitt brus + Digital Triangle wave Digital Triangelvåg + Digital Saw wave Digital Sågtandsvåg + Digital Ramp wave + Digital Square wave + Digital Moog saw wave + Triangle wave Triangelvåg + Saw wave Sågtandsvåg + Ramp wave - + Rampvåg + Square wave Fyrkantvåg + Moog saw wave Moog sågtandsvåg + Abs. sine wave Abs. sinusvåg + Random Slumpmässig + Random smooth - + Slumpmässigt slät MonstroView + Operators view - + Operatörernas vy + The Operators view contains all the operators. These include both audible operators (oscillators) and inaudible operators, or modulators: Low-frequency oscillators and Envelopes. Knobs and other widgets in the Operators view have their own what's this -texts, so you can get more specific help for them that way. + Matrix view + The Matrix view contains the modulation matrix. Here you can define the modulation relationships between the various operators: Each audible operator (oscillators 1-3) has 3-4 properties that can be modulated by any of the modulators. Using more modulations consumes more CPU power. The view is divided to modulation targets, grouped by the target oscillator. Available targets are volume, pitch, phase, pulse width and sub-osc ratio. Note: some targets are specific to one oscillator only. @@ -4645,256 +5836,407 @@ Each modulation target has 4 knobs, one for each modulator. By default the knobs + + + + Volume + Volym + + + + + + Panning + Panorering + + + + + + Coarse detune + + + + + + + semitones + halvtoner + + + + + Finetune left + + + + + + + + cents + + + + + + Finetune right + + + + + + + Stereo phase offset + + + + + + + + + deg + + + + + Pulse width + + + + + Send sync on pulse rise + + + + + Send sync on pulse fall + + + + + Hard sync oscillator 2 + + + + + Reverse sync oscillator 2 + + + + + Sub-osc mix + + + + + Hard sync oscillator 3 + + + + + Reverse sync oscillator 3 + + + + + + + + Attack + Attack + + + + + Rate + Värdera + + + + + Phase + Fas + + + + + Pre-delay + + + + + + Hold + Håll + + + + + Decay + Decay + + + + + Sustain + Sustain + + + + + Release + Släpp + + + + + Slope + Lutning + + + Mix Osc2 with Osc3 Mixa Osc2 med Osc3 + Modulate amplitude of Osc3 with Osc2 Modulera amplituden för Osc3 med Osc2 + Modulate frequency of Osc3 with Osc2 Modulera frekvensen för Osc3 med Osc2 + Modulate phase of Osc3 with Osc2 Modulera fasen för Osc3 med Osc2 + The CRS knob changes the tuning of oscillator 1 in semitone steps. + The CRS knob changes the tuning of oscillator 2 in semitone steps. + The CRS knob changes the tuning of oscillator 3 in semitone steps. + + + + FTL and FTR change the finetuning of the oscillator for left and right channels respectively. These can add stereo-detuning to the oscillator which widens the stereo image and causes an illusion of space. + + + The SPO knob modifies the difference in phase between left and right channels. Higher difference creates a wider stereo image. + The PW knob controls the pulse width, also known as duty cycle, of oscillator 1. Oscillator 1 is a digital pulse wave oscillator, it doesn't produce bandlimited output, which means that you can use it as an audible oscillator but it will cause aliasing. You can also use it as an inaudible source of a sync signal, which can be used to synchronize oscillators 2 and 3. + Send Sync on Rise: When enabled, the Sync signal is sent every time the state of oscillator 1 changes from low to high, ie. when the amplitude changes from -1 to 1. Oscillator 1's pitch, phase and pulse width may affect the timing of syncs, but its volume has no effect on them. Sync signals are sent independently for both left and right channels. + Send Sync on Fall: When enabled, the Sync signal is sent every time the state of oscillator 1 changes from high to low, ie. when the amplitude changes from 1 to -1. Oscillator 1's pitch, phase and pulse width may affect the timing of syncs, but its volume has no effect on them. Sync signals are sent independently for both left and right channels. + + Hard sync: Every time the oscillator receives a sync signal from oscillator 1, its phase is reset to 0 + whatever its phase offset is. - + Hard sync: varje gång oscillatorn tar emot en synkroniseringssignal från oscillator 1 återställs dess fas till 0 + vad dess fasförskjutning är. + + Reverse sync: Every time the oscillator receives a sync signal from oscillator 1, the amplitude of the oscillator gets inverted. + Choose waveform for oscillator 2. Välj vågform för oscillator 2. + Choose waveform for oscillator 3's first sub-osc. Oscillator 3 can smoothly interpolate between two different waveforms. + Choose waveform for oscillator 3's second sub-osc. Oscillator 3 can smoothly interpolate between two different waveforms. + The SUB knob changes the mixing ratio of the two sub-oscs of oscillator 3. Each sub-osc can be set to produce a different waveform, and oscillator 3 can smoothly interpolate between them. All incoming modulations to oscillator 3 are applied to both sub-oscs/waveforms in the exact same way. + In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. Mix mode means no modulation: the outputs of the oscillators are simply mixed together. + In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. AM means amplitude modulation: Oscillator 3's amplitude (volume) is modulated by oscillator 2. + In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. FM means frequency modulation: Oscillator 3's frequency (pitch) is modulated by oscillator 2. The frequency modulation is implemented as phase modulation, which gives a more stable overall pitch than "pure" frequency modulation. + In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. PM means phase modulation: Oscillator 3's phase is modulated by oscillator 2. It differs from frequency modulation in that the phase changes are not cumulative. + Select the waveform for LFO 1. "Random" and "Random smooth" are special waveforms: they produce random output, where the rate of the LFO controls how often the state of the LFO changes. The smooth version interpolates between these states with cosine interpolation. These random modes can be used to give "life" to your presets - add some of that analog unpredictability... + Select the waveform for LFO 2. "Random" and "Random smooth" are special waveforms: they produce random output, where the rate of the LFO controls how often the state of the LFO changes. The smooth version interpolates between these states with cosine interpolation. These random modes can be used to give "life" to your presets - add some of that analog unpredictability... + + Attack causes the LFO to come on gradually from the start of the note. + + Rate sets the speed of the LFO, measured in milliseconds per cycle. Can be synced to tempo. + + PHS controls the phase offset of the LFO. + + PRE, or pre-delay, delays the start of the envelope from the start of the note. 0 means no delay. + + ATT, or attack, controls how fast the envelope ramps up at start, measured in milliseconds. A value of 0 means instant. + + HOLD controls how long the envelope stays at peak after the attack phase. + + DEC, or decay, controls how fast the envelope falls off from its peak, measured in milliseconds it would take to go from peak to zero. The actual decay may be shorter if sustain is used. + + SUS, or sustain, controls the sustain level of the envelope. The decay phase will not go below this level as long as the note is held. + + REL, or release, controls how long the release is for the note, measured in how long it would take to fall from peak to zero. Actual release may be shorter, depending on at what phase the note is released. + + The slope knob controls the curve or shape of the envelope. A value of 0 creates straight rises and falls. Negative values create curves that start slowly, peak quickly and fall of slowly again. Positive values create curves that start and end quickly, and stay longer near the peaks. - Volume - Volym - - - Panning - Panorering - - - Coarse detune - - - - semitones - halvtoner - - - Finetune left - - - - cents - - - - Finetune right - - - - Stereo phase offset - - - - deg - - - - Pulse width - - - - Send sync on pulse rise - - - - Send sync on pulse fall - - - - Hard sync oscillator 2 - - - - Reverse sync oscillator 2 - - - - Sub-osc mix - - - - Hard sync oscillator 3 - - - - Reverse sync oscillator 3 - - - - Attack - Attack - - - Rate - Värdera - - - Phase - - - - Pre-delay - - - - Hold - Håll - - - Decay - Decay - - - Sustain - Sustain - - - Release - Släpp - - - Slope - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Modulation amount Moduleringsmängd @@ -4902,34 +6244,42 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator MultitapEchoControlDialog + Length Längd + Step length: + Dry + Dry Gain: + Stages - + Stadier + Lowpass stages: + Swap inputs + Swap left and right input channel for reflections @@ -4937,82 +6287,102 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator NesInstrument + Channel 1 Coarse detune + Channel 1 Volume - + Kanal 1 volym + Channel 1 Envelope length + Channel 1 Duty cycle + Channel 1 Sweep amount + Channel 1 Sweep rate + Channel 2 Coarse detune + Channel 2 Volume - + Kanal 2 volym + Channel 2 Envelope length + Channel 2 Duty cycle + Channel 2 Sweep amount + Channel 2 Sweep rate + Channel 3 Coarse detune + Channel 3 Volume - + Kanal 3 volym + Channel 4 Volume - + Kanal 4 volym + Channel 4 Envelope length + Channel 4 Noise frequency + Channel 4 Noise frequency sweep + Master volume Huvudvolym + Vibrato @@ -5020,114 +6390,155 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator NesInstrumentView + + + + Volume Volym + + + Coarse detune + + + Envelope length + Enable channel 1 - + Aktivera kanal 1 + Enable envelope 1 + Enable envelope 1 loop + Enable sweep 1 - + Aktivera svep 1 + + Sweep amount - + Svepmängd + + Sweep rate - + Svephastighet + + 12.5% Duty cycle + + 25% Duty cycle + + 50% Duty cycle + + 75% Duty cycle + Enable channel 2 - + Aktivera kanal 2 + Enable envelope 2 + Enable envelope 2 loop + Enable sweep 2 + Enable channel 3 - + Aktivera kanal 3 + Noise Frequency - + Brusfrekvens + Frequency sweep + Enable channel 4 - + Aktivera kanal 4 + Enable envelope 4 + Enable envelope 4 loop + Quantize noise frequency when using note frequency - + Kvantifiera brusfrekvens vid användning av notfrekvens + Use note frequency for noise - + Använd notfrekvens för brus + Noise mode - + Brusläge + Master Volume - + Huvudvolym + Vibrato @@ -5135,81 +6546,103 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator OscillatorObject - Osc %1 volume - - - - Osc %1 panning - - - - Osc %1 coarse detuning - - - - Osc %1 fine detuning left - - - - Osc %1 fine detuning right - - - - Osc %1 phase-offset - - - - Osc %1 stereo phase-detuning - - - - Osc %1 wave shape - - - - Modulation type %1 - - - + Osc %1 waveform + Osc %1 harmonic + + + + Osc %1 volume + Osc %1 volym + + + + + Osc %1 panning + Osc %1 panorering + + + + + Osc %1 fine detuning left + + + + + Osc %1 coarse detuning + + + + + Osc %1 fine detuning right + + + + + Osc %1 phase-offset + + + + + Osc %1 stereo phase-detuning + + + + + Osc %1 wave shape + + + + + Modulation type %1 + Moduleringstyp %1 + PatchesDialog + Qsynth: Channel Preset - + Qsynth: Kanal förinställd + Bank selector - + Bankväljare + Bank Bank + Program selector - + Programväljare + Patch + Name Namn + OK OK + Cancel Avbryt @@ -5217,46 +6650,57 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator PatmanView + Open other patch + Click here to open another patch-file. Loop and Tune settings are not reset. + Loop - + Slinga + Loop mode - + Slinga-läge + Here you can toggle the Loop mode. If enabled, PatMan will use the loop information available in the file. + Tune - + Tune + Tune mode - + Tune-läge + Here you can toggle the Tune mode. If enabled, PatMan will tune the sample to match the note's frequency. + No file selected Ingen fil vald + Open patch file Öppna patch-fil + Patch-Files (*.pat) Patch-filer (*.pat) @@ -5264,53 +6708,65 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator PatternView - Open in piano-roll - Öppna i pianorulle - - - Clear all notes - Rensa alla noter - - - Reset name - Nollställ namn - - - Change name - Byt namn - - - Add steps - Lägg till steg - - - Remove steps - Ta bort steg - - + use mouse wheel to set velocity of a step - + använd mushjulet för att ställa in hastigheten på ett steg + double-click to open in Piano Roll Dubbelklicka för att öppna i Pianorulle + + Open in piano-roll + Öppna i pianorulle + + + + Clear all notes + Rensa alla noter + + + + Reset name + Nollställ namn + + + + Change name + Byt namn + + + + Add steps + Lägg till steg + + + + Remove steps + Ta bort steg + + + Clone Steps - Klona steg + Klona Steg PeakController + Peak Controller + Peak Controller Bug + Due to a bug in older version of LMMS, the peak controllers may not be connect properly. Please ensure that peak controllers are connected properly and re-save this file. Sorry for any inconvenience caused. @@ -5318,10 +6774,12 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator PeakControllerDialog + PEAK + LFO Controller @@ -5329,353 +6787,438 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator PeakControllerEffectControlDialog + BASE + Base amount: - Modulation amount: - Moduleringsmängd: - - - Attack: - Attack: - - - Release: - Release: - - + AMNT + + Modulation amount: + Moduleringsmängd: + + + MULT + Amount Multiplicator: + ATCK + + Attack: + Attack: + + + DCAY - Treshold: + + Release: + Release: + + + + TRSH - TRSH - + + Treshold: + Tröskelvärde: PeakControllerEffectControls + Base value Basvärde + Modulation amount Moduleringsmängd - Mute output - Tysta utgångs-ljud - - + Attack Attack + Release Släpp + + Treshold + Tröskelvärde + + + + Mute output + Tysta utgångs-ljud + + + Abs Value Abs-värde + Amount Multiplicator - - Treshold - - PianoRoll - Please open a pattern by double-clicking on it! - Dubbelklicka för att öppna ett mönster! - - - Last note - Senaste noten - - - Note lock - - - + Note Velocity - + Nothastighet + Note Panning Not-panorering + Mark/unmark current semitone Markera/avmarkera nuvarande halvton + + Mark/unmark all corresponding octave semitones + Markera/avmarkera alla motsvarande oktavhalvtoner + + + Mark current scale Markera nuvarande skala + Mark current chord Markera nuvarande ackord + Unmark all Avmarkera allt + + Select all notes on this key + Välj alla noter på denna tangent + + + + Note lock + Notlås + + + + Last note + Senaste noten + + + No scale Ingen skala + No chord Inget ackord + Velocity: %1% - + Hastighet: %1% + Panning: %1% left Panorering: %1% vänster + Panning: %1% right Panorering: %1% höger + Panning: center Panorering: center + + Please open a pattern by double-clicking on it! + Dubbelklicka för att öppna ett mönster! + + + + Please enter a new value between %1 and %2: Ange ett nytt värde mellan %1 och %2: - - Mark/unmark all corresponding octave semitones - - - - Select all notes on this key - Välj alla noter på denna tangent - PianoRollWindow + Play/pause current pattern (Space) Spela/pausa aktuellt mönster (mellanslag) + Record notes from MIDI-device/channel-piano Spela in noter från MIDI-enhet/kanal-piano + Record notes from MIDI-device/channel-piano while playing song or BB track Spela in noter från MIDI-enhet/kanal-piano medan sång eller BB-spår spelas + Stop playing of current pattern (Space) Sluta spela aktuellt mönster (mellanslag) + Click here to play the current pattern. This is useful while editing it. The pattern is automatically looped when its end is reached. Klicka här för att spela det aktuella mönstret, detta är användbart när man redigerar. Mönstret spelas från början igen när det nått sitt slut. + Click here to record notes from a MIDI-device or the virtual test-piano of the according channel-window to the current pattern. When recording all notes you play will be written to this pattern and you can play and edit them afterwards. + Click here to record notes from a MIDI-device or the virtual test-piano of the according channel-window to the current pattern. When recording all notes you play will be written to this pattern and you will hear the song or BB track in the background. + Click here to stop playback of current pattern. Klicka här för att stoppa uppspelning av de aktuella mönstret. - Draw mode (Shift+D) - Ritläge (Shift+D) - - - Erase mode (Shift+E) - Suddläge (Shift+E) - - - Select mode (Shift+S) - Markeringsläge (Shift+S) - - - Detune mode (Shift+T) - - - - Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold %1 to temporarily go into select mode. - - - - Click here and erase mode will be activated. In this mode you can erase notes. You can also press 'Shift+E' on your keyboard to activate this mode. - - - - Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold %1 in draw mode to temporarily use select mode. - - - - Click here and detune mode will be activated. In this mode you can click a note to open its automation detuning. You can utilize this to slide notes from one to another. You can also press 'Shift+T' on your keyboard to activate this mode. - - - - Cut selected notes (%1+X) - Klipp ut valda noter (%1+X) - - - Copy selected notes (%1+C) - Kopiera valda noter (%1+C) - - - Paste notes from clipboard (%1+V) - Klistra in noter (%1+V) - - - Click here and the selected notes will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. - - - - Click here and the selected notes will be copied into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. - - - - Click here and the notes from the clipboard will be pasted at the first visible measure. - - - - This controls the magnification of an axis. It can be helpful to choose magnification for a specific task. For ordinary editing, the magnification should be fitted to your smallest notes. - - - - The 'Q' stands for quantization, and controls the grid size notes and control points snap to. With smaller quantization values, you can draw shorter notes in Piano Roll, and more exact control points in the Automation Editor. - - - - This lets you select the length of new notes. 'Last Note' means that LMMS will use the note length of the note you last edited - - - - The feature is directly connected to the context-menu on the virtual keyboard, to the left in Piano Roll. After you have chosen the scale you want in this drop-down menu, you can right click on a desired key in the virtual keyboard, and then choose 'Mark current Scale'. LMMS will highlight all notes that belongs to the chosen scale, and in the key you have selected! - - - - Let you select a chord which LMMS then can draw or highlight.You can find the most common chords in this drop-down menu. After you have selected a chord, click anywhere to place the chord, and right click on the virtual keyboard to open context menu and highlight the chord. To return to single note placement, you need to choose 'No chord' in this drop-down menu. - - - + Edit actions Redigera åtgärder + + Draw mode (Shift+D) + Ritläge (Skift+D) + + + + Erase mode (Shift+E) + Suddläge (Skift+E) + + + + Select mode (Shift+S) + Markeringsläge (Skift+S) + + + + Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold %1 to temporarily go into select mode. + Klicka här och ritläget kommer att aktiveras. I det här läget kan du lägga till, ändra storlek och flytta anteckningar. Detta är standardläget som används för det mesta. Du kan också trycka på 'Shift+D' på tangentbordet för att aktivera det här läget. I det här läget håller du %1 intryckt för att tillfälligt gå in i välja-läget. + + + + Click here and erase mode will be activated. In this mode you can erase notes. You can also press 'Shift+E' on your keyboard to activate this mode. + Klicka här och radera-läge kommer att aktiveras. I det här läget kan du radera anteckningar. Du kan också trycka på "Skift+E" på tangentbordet för att aktivera det här läget. + + + + Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold %1 in draw mode to temporarily use select mode. + Klicka här och välja-läget aktiveras. I det här läget kan du välja anteckningar. Alternativt kan du hålla %1 i ritläget för att tillfälligt använda välja-läget. + + + + Pitch Bend mode (Shift+T) + + + + + Click here and Pitch Bend mode will be activated. In this mode you can click a note to open its automation detuning. You can utilize this to slide notes from one to another. You can also press 'Shift+T' on your keyboard to activate this mode. + + + + + Quantize + + + + Copy paste controls + + Cut selected notes (%1+X) + Klipp ut valda noter (%1+X) + + + + Copy selected notes (%1+C) + Kopiera valda noter (%1+C) + + + + Paste notes from clipboard (%1+V) + Klistra in noter (%1+V) + + + + Click here and the selected notes will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. + Klicka här och de valda noterna kommer att klippas ut till urklipp. Du kan klistra in dem var som helst i något mönster genom att klicka på knappen klistra in. + + + + Click here and the selected notes will be copied into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. + Klicka här och de valda anteckningarna kopieras till urklipp. Du kan klistra in dem var som helst i något mönster genom att klicka på knappen klistra in. + + + + Click here and the notes from the clipboard will be pasted at the first visible measure. + + + + Timeline controls Tidslinjekontroller + Zoom and note controls + + This controls the magnification of an axis. It can be helpful to choose magnification for a specific task. For ordinary editing, the magnification should be fitted to your smallest notes. + + + + + The 'Q' stands for quantization, and controls the grid size notes and control points snap to. With smaller quantization values, you can draw shorter notes in Piano Roll, and more exact control points in the Automation Editor. + + + + + This lets you select the length of new notes. 'Last Note' means that LMMS will use the note length of the note you last edited + + + + + The feature is directly connected to the context-menu on the virtual keyboard, to the left in Piano Roll. After you have chosen the scale you want in this drop-down menu, you can right click on a desired key in the virtual keyboard, and then choose 'Mark current Scale'. LMMS will highlight all notes that belongs to the chosen scale, and in the key you have selected! + + + + + Let you select a chord which LMMS then can draw or highlight.You can find the most common chords in this drop-down menu. After you have selected a chord, click anywhere to place the chord, and right click on the virtual keyboard to open context menu and highlight the chord. To return to single note placement, you need to choose 'No chord' in this drop-down menu. + + + + + Piano-Roll - %1 Pianorulle - %1 + + Piano-Roll - no pattern Pianorulle - inget mönster - - Quantize - - PianoView + Base note - Bas-not + Basnot Plugin + Plugin not found - Plugin hittades inte + Instickmodulen hittades inte + The plugin "%1" wasn't found or could not be loaded! Reason: "%2" - Pluginet "%1" hittades inte eller kunde inte laddas! + Instickmodulen "%1" hittades inte eller kunde inte läsas in! Orsak: "%2" + Error while loading plugin - Fel vid inläsning av plugin + Fel vid inläsning av instickmodulen + Failed to load plugin "%1"! - Misslyckades att läsa in plugin "%1"! + Misslyckades att läsa in insticksmodulen "%1"! PluginBrowser - Instrument browser - - - - Drag an instrument into either the Song-Editor, the Beat+Bassline Editor or into an existing instrument track. - - - + Instrument Plugins - + Instrument insticksmoduler + + + + Instrument browser + Instrument bläddrare + + + + Drag an instrument into either the Song-Editor, the Beat+Bassline Editor or into an existing instrument track. + Dra ett instrument till antingen Låtredigeraren, Takt+Basgång-redigeraren eller till ett befintligt instrument spår. PluginFactory + Plugin not found. - Plugin hittades inte. + Insticksmodulen hittades inte. + LMMS plugin %1 does not have a plugin descriptor named %2! @@ -5683,118 +7226,147 @@ Orsak: "%2" ProjectNotes - Project notes + + Project Notes Projektanteckningar - Put down your project notes here. - Skriv ner dina anteckningar för projektet här. + + Enter project notes here + + Edit Actions - Redigera Händelser + Redigera Åtgärder + &Undo &Ångra + %1+Z - + %1+Z + &Redo &Gör om + %1+Y - + %1+Y + &Copy &Kopiera + %1+C - + %1+C + Cu&t Klipp u&t + %1+X - + %1+X + &Paste &Klistra in + %1+V %1+V + Format Actions + &Bold &Fet + %1+B %1+B + &Italic &Kursiv + %1+I %1+I + &Underline &Understruken + %1+U %1+U + &Left &Vänster + %1+L %1+L + C&enter C&entrera + %1+E %1+E + &Right &Höger + %1+R %1+R + &Justify - + &Justera + %1+J %1+J + &Color... &Färg... @@ -5802,680 +7374,985 @@ Orsak: "%2" ProjectRenderer + WAV-File (*.wav) WAV-Fil (*.wav) + Compressed OGG-File (*.ogg) Komprimerad OGG-Fil (*.ogg) + + + Compressed MP3-File (*.mp3) + Komprimerad MP3-fil ( *.mp3) + QWidget + + + Name: Namn: + + Maker: Skapare: + + Copyright: Copyright: + + Requires Real Time: + + + + + + Yes Ja + + + + + + No Nej + + Real Time Capable: + + In Place Broken: + + Channels In: Kanaler In: + + Channels Out: Kanaler Ut: - File: - Fil: - - + File: %1 Fil: %1 + + + File: + Fil: + RenameDialog + Rename... Byt namn... + + ReverbSCControlDialog + + + Input + Ingång + + + + Input Gain: + Input Förstärkning: + + + + Size + Storlek + + + + Size: + Storlek: + + + + Color + Färg + + + + Color: + Färg: + + + + Output + Utgång + + + + Output Gain: + Output Förstärkning + + + + ReverbSCControls + + + Input Gain + Ingångsförstärkning + + + + Size + Storlek + + + + Color + Färg + + + + Output Gain + Utgångsförstärkning + + SampleBuffer + + Fail to open file + Misslyckas med att öppna filen + + + + Audio files are limited to %1 MB in size and %2 minutes of playing time + Ljudfiler är begränsade till %1 MB i storlek och %2 minuters speltid + + + Open audio file Öppna ljudfil - Wave-Files (*.wav) - Wave-Filer (*.wav) - - - OGG-Files (*.ogg) - OGG-Filer (*.ogg) - - - DrumSynth-Files (*.ds) - - - - FLAC-Files (*.flac) - FLAC-Filer (*.flac) - - - SPEEX-Files (*.spx) - - - - VOC-Files (*.voc) - VOC-Filer - (*.voc) - - - AIFF-Files (*.aif *.aiff) - AIFF-Filer (*.aif *.aiff) - - - AU-Files (*.au) - AU-Filer (*.au) - - - RAW-Files (*.raw) - RAW-Filer (*.raw) - - + All Audio-Files (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw) - Alla Ljudfiler (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw) + Alla ljudfiler (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw) + + + + Wave-Files (*.wav) + Wave-filer (*.wav) + + + + OGG-Files (*.ogg) + OGG-filer (*.ogg) + + + + DrumSynth-Files (*.ds) + DrumSynth-filer (*.ds) + + + + FLAC-Files (*.flac) + FLAC-filer (*.flac) + + + + SPEEX-Files (*.spx) + SPEEX-filer (*.spx) + + + + VOC-Files (*.voc) + VOC-filer (*.voc) + + + + AIFF-Files (*.aif *.aiff) + AIFF-filer (*.aif *.aiff) + + + + AU-Files (*.au) + AU-filer (*.au) + + + + RAW-Files (*.raw) + RAW-filer (*.raw) SampleTCOView + double-click to select sample dubbelklicka för att välja ljudfil + Delete (middle mousebutton) Ta bort (musens mitt-knapp) + Cut Klipp ut + Copy Kopiera + Paste Klistra in + Mute/unmute (<%1> + middle click) - + Tysta/avtysta (<%1> + mittenklick) SampleTrack - Sample track - Ljudfils-spår - - + Volume Volym + Panning Panorering + + + + Sample track + Ljudspår + SampleTrackView + Track volume - + Spårvolym + Channel volume: - + Kanalvolym: + VOL VOL + Panning Panorering + Panning: Panorering: + PAN - PANORERA + PAN SetupDialog + Setup LMMS Ställ in LMMS + + General settings - + Allmänna inställningar + BUFFER SIZE - + BUFFERTSTORLEK + + Reset to default-value Återställ till standardvärde + MISC + Enable tooltips - Aktivera verktygs-tips + Aktivera verktygstips + Show restart warning after changing settings - + Visa omstartsvarning efter att ha ändrat inställningar + Display volume as dBFS Visa volym som dBFS + Compress project files per default Komprimera projektfiler som standard + One instrument track window mode + HQ-mode for output audio-device - + HQ-läge för ljudenhetsutgång + Compact track buttons - + Kompakta spårknappar + Sync VST plugins to host playback + Enable note labels in piano roll Visa noter i pianorulle + Enable waveform display by default - + Aktivera vågformsvisning som standard + Keep effects running even without input - + Håll effekter igång även utan ingång + Create backup file when saving a project Skapa en backup-fil när ett projekt sparas + + Reopen last project on start + Öppna senaste projektet vid start + + + + Use built-in NaN handler + Använd inbyggd NaN-hanterare + + + + PLUGIN EMBEDDING + + + + + No embedding + + + + + Embed using Qt API + + + + + Embed using native Win32 API + + + + + Embed using XEmbed protocol + + + + LANGUAGE SPRÅK + + Paths Sökvägar - LMMS working directory - LMMS arbetskatalog - - - VST-plugin directory - Katalog för VST-plugin - - - Background artwork - - - - STK rawwave directory - Katalog för STK rå-vågform - - - Default Soundfont File - - - - Performance settings - - - - UI effects vs. performance - - - - Smooth scroll in Song Editor - Mjuk rullning i Sång-editorn - - - Show playback cursor in AudioFileProcessor - - - - Audio settings - - - - AUDIO INTERFACE - - - - MIDI settings - MIDI-inställningar - - - MIDI INTERFACE - - - - OK - OK - - - Cancel - Avbryt - - - Restart LMMS - Starta om LMMS - - - Please note that most changes won't take effect until you restart LMMS! - Många av ändringarna kommer inte gälla förrän LMMS startats om! - - - Frames: %1 -Latency: %2 ms - - - - Here you can setup the internal buffer-size used by LMMS. Smaller values result in a lower latency but also may cause unusable sound or bad performance, especially on older computers or systems with a non-realtime kernel. - - - - Choose LMMS working directory - Välj arbetskatalog för LMMS - - - Choose your VST-plugin directory - Välj katalog för dina VST-plugin - - - Choose artwork-theme directory - Välj katalog för gränssnitts-tema - - - Choose LADSPA plugin directory - Välj katalog för LADSPA-plugin - - - Choose STK rawwave directory - Välj katalog för STK-råfiler - - - Choose default SoundFont - Välj standard-SoundFont - - - Choose background artwork - Välj bakgrunds-grafik - - - Here you can select your preferred audio-interface. Depending on the configuration of your system during compilation time you can choose between ALSA, JACK, OSS and more. Below you see a box which offers controls to setup the selected audio-interface. - - - - Here you can select your preferred MIDI-interface. Depending on the configuration of your system during compilation time you can choose between ALSA, OSS and more. Below you see a box which offers controls to setup the selected MIDI-interface. - - - - Reopen last project on start - - - + Directories Kataloger + + LMMS working directory + LMMS-arbetsmapp + + + Themes directory - Katalog för teman + Mapp för teman + + Background artwork + Bakgrund konstverk + + + + VST-plugin directory + Mapp för VST-insticksmoduler + + + GIG directory - Katalog för GIG-filer + Mapp för GIG-filer + SF2 directory - Katalog för SF2-filer + Mapp för SF2-filer + LADSPA plugin directories - Katalog för LADSPA-plugins + Katalog för LADSPA-insticksmoduler + + STK rawwave directory + Mapp för STK rå-vågform + + + + Default Soundfont File + Standard Soundfont-fil + + + + + Performance settings + Prestandainställningar + + + Auto save - Autospara + Spara automatiskt + + Enable auto-save + Aktivera automatisk sparande + + + + Allow auto-save while playing + Tillåt automatisk sparande när du spelar + + + + UI effects vs. performance + UI-effekter vs. prestanda + + + + Smooth scroll in Song Editor + Mjuk rullning i Låtredigeraren + + + + Show playback cursor in AudioFileProcessor + Visa uppspelningsmarkören i AudioFileProcessor + + + + + Audio settings + Ljudinställningar + + + + AUDIO INTERFACE + LJUDGRÄNSSNITT + + + + + MIDI settings + MIDI-inställningar + + + + MIDI INTERFACE + MIDIGRÄNSSNITT + + + + OK + OK + + + + Cancel + Avbryt + + + + Restart LMMS + Starta om LMMS + + + + Please note that most changes won't take effect until you restart LMMS! + Många av ändringarna kommer inte gälla förrän LMMS startats om! + + + + Frames: %1 +Latency: %2 ms + Ramar: %1 +Latens: %2 ms + + + + Here you can setup the internal buffer-size used by LMMS. Smaller values result in a lower latency but also may cause unusable sound or bad performance, especially on older computers or systems with a non-realtime kernel. + Här kan du ställa in den interna buffertstorleken som används av LMMS. Mindre värden resulterar i en lägre latens men kan också orsaka oanvändbart ljud eller dålig prestanda, särskilt på äldre datorer eller system med en icke-realtidskernel. + + + + Choose LMMS working directory + Välj LMMS-arbetsmapp + + + Choose your GIG directory - Välj din GIG-katalog + Välj din GIG-mapp + Choose your SF2 directory - Välj din SF2-katalog + Välj din SF2-mapp + + Choose your VST-plugin directory + Välj mapp för dina VST-insticksmoduler + + + + Choose artwork-theme directory + Välj mapp för gränssnitts-tema + + + + Choose LADSPA plugin directory + Välj mapp för LADSPA-insticksmoduler + + + + Choose STK rawwave directory + Välj mapp för STK-rawwave + + + + Choose default SoundFont + Välj standard-SoundFont + + + + Choose background artwork + Välj bakgrunds-grafik + + + minutes minuter + minute minut - Enable auto-save - - - - Allow auto-save while playing - - - + Disabled - + Inaktiverad + Auto-save interval: %1 - + Automatiskt sparande intervall: %1 + Set the time between automatic backup to %1. Remember to also save your project manually. You can choose to disable saving while playing, something some older systems find difficult. + + + Here you can select your preferred audio-interface. Depending on the configuration of your system during compilation time you can choose between ALSA, JACK, OSS and more. Below you see a box which offers controls to setup the selected audio-interface. + + + + + Here you can select your preferred MIDI-interface. Depending on the configuration of your system during compilation time you can choose between ALSA, OSS and more. Below you see a box which offers controls to setup the selected MIDI-interface. + + Song + Tempo Tempo + Master volume Huvudvolym + Master pitch - Project saved - Projekt sparat - - - The project %1 is now saved. - Projektet %1 är nu sparat. - - - Project NOT saved. - Projektet är INTE sparat. - - - The project %1 was not saved! - Projektet %1 sparades inte! - - - Import file - Importera fil - - - MIDI sequences - MIDI-sekvenser - - - Hydrogen projects - - - - All file types - Alla filtyper - - - Empty project - Tomt projekt - - - This project is empty so exporting makes no sense. Please put some items into Song Editor first! - Projektet är tomt, export är meningslöst. Skapa något i Sång-editorn innan du exporterar! - - - Select directory for writing exported tracks... - - - - untitled - namnlös - - - Select file for project-export... - - - - The following errors occured while loading: - - - - MIDI File (*.mid) - MIDI-fil (*.mid) - - + LMMS Error report LMMS Felrapport - Save project + + Project saved + Projekt sparat + + + + The project %1 is now saved. + Projektet %1 är nu sparat. + + + + Project NOT saved. + Projektet är INTE sparat. + + + + The project %1 was not saved! + Projektet %1 sparades inte! + + + + Import file + Importera fil + + + + MIDI sequences + MIDI-sekvenser + + + + Hydrogen projects + + + All file types + Alla filtyper + + + + + Empty project + Tomt projekt + + + + + This project is empty so exporting makes no sense. Please put some items into Song Editor first! + Projektet är tomt, export är meningslöst. Skapa något i Låtredigeraren innan du exporterar! + + + + Select directory for writing exported tracks... + Välj mapp för att skriva exporterade spår... + + + + + untitled + namnlös + + + + + Select file for project-export... + Välj fil för projekt-export... + + + + Save project + Spara projekt + + + + MIDI File (*.mid) + MIDI-fil (*.mid) + + + + The following errors occured while loading: + Följande fel inträffade under inläsning: + SongEditor + Could not open file - kunde inte öppna fil + Kunde inte öppna fil + + Could not open file %1. You probably have no permissions to read this file. + Please make sure to have at least read permissions to the file and try again. + Det gick inte att öppna filen %1. Du har förmodligen inga behörigheter att läsa den här filen. + Se till att ha åtminstone läsbehörigheter till filen och försök igen. + + + Could not write file Kunde inte skriva fil - Could not open file %1. You probably have no permissions to read this file. - Please make sure to have at least read permissions to the file and try again. - - - - Error in file - Fil-fel - - - The file %1 seems to contain errors and therefore can't be loaded. - - - - Tempo - Tempo - - - TEMPO/BPM - TEMPO/BPM - - - tempo of song - Sångtempo - - - The tempo of a song is specified in beats per minute (BPM). If you want to change the tempo of your song, change this value. Every measure has four beats, so the tempo in BPM specifies, how many measures / 4 should be played within a minute (or how many measures should be played within four minutes). - - - - High quality mode - - - - Master volume - Huvudvolym - - - master volume - huvudvolym - - - Master pitch - - - - master pitch - - - - Value: %1% - Värde: %1% - - - Value: %1 semitones - Värde: %1 halvtoner - - + Could not open %1 for writing. You probably are not permitted to write to this file. Please make sure you have write-access to the file and try again. - + Det gick inte att öppna %1 för att skriva. Du har förmodligen inte tillåtelse att skriva till den här filen. Se till att du har skrivåtkomst till filen och försök igen. - template - mall + + Error in file + Fel i filen - project - projekt + + The file %1 seems to contain errors and therefore can't be loaded. + Filen %1 verkar innehålla fel och kan därför inte läsas in. + Version difference Versions-skillnad + This %1 was created with LMMS %2. + Detta %1 skapades med LMMS %2. + + + + template + mall + + + + project + projekt + + + + Tempo + Tempo + + + + TEMPO/BPM + TEMPO/BPM + + + + tempo of song + Sångtempo + + + + The tempo of a song is specified in beats per minute (BPM). If you want to change the tempo of your song, change this value. Every measure has four beats, so the tempo in BPM specifies, how many measures / 4 should be played within a minute (or how many measures should be played within four minutes). + + + High quality mode + Hög kvalitet läge + + + + + Master volume + Huvudvolym + + + + master volume + huvudvolym + + + + + Master pitch + + + + + master pitch + + + + + Value: %1% + Värde: %1% + + + + Value: %1 semitones + Värde: %1 halvtoner + SongEditorWindow + Song-Editor - Sång-Editor + Låtredigerare + Play song (Space) Spela sång (Mellanslag) + Record samples from Audio-device - + Spela in samplingar från ljudenheten + Record samples from Audio-device while playing song or BB track - + Spela in samplingar från ljudenheten medan du spelar låten eller BB-spåret + Stop song (Space) Sluta spela sång (Mellanslag) - Add beat/bassline - Lägg till trummor/bas - - - Add sample-track - Lägg till ljudfils-spår - - - Add automation-track - Lägg till automationsspår - - - Draw mode - Ritläge - - - Edit mode (select and move) - Redigeringsläge (välj och flytta) - - + Click here, if you want to play your whole song. Playing will be started at the song-position-marker (green). You can also move it while playing. - + Klicka här, om du vill spela hela din låt. Uppspelningen startas vid sångplaceringsmarkören (grön). Du kan också flytta den medan du spelar. + Click here, if you want to stop playing of your song. The song-position-marker will be set to the start of your song. + Track actions - + Spåråtgärder + + Add beat/bassline + Lägg till takt/basgång + + + + Add sample-track + Lägg till ljudspår + + + + Add automation-track + Lägg till automationsspår + + + Edit actions Redigera åtgärder + + Draw mode + Ritläge + + + + Edit mode (select and move) + Redigeringsläge (välj och flytta) + + + Timeline controls Tidslinjekontroller + Zoom controls Zoomningskontroller @@ -6483,10 +8360,12 @@ Remember to also save your project manually. You can choose to disable saving wh SpectrumAnalyzerControlDialog + Linear spectrum - + Linjärt spektrum + Linear Y axis Linjär Y-axel @@ -6494,29 +8373,35 @@ Remember to also save your project manually. You can choose to disable saving wh SpectrumAnalyzerControls + Linear spectrum - + Linjärt spektrum + Linear Y axis Linjär Y-axel + Channel mode - + Kanalläge SubWindow + Close Stäng + Maximize Maximera + Restore Återställ @@ -6524,6 +8409,8 @@ Remember to also save your project manually. You can choose to disable saving wh TabWidget + + Settings for %1 Inställningar för %1 @@ -6531,105 +8418,131 @@ Remember to also save your project manually. You can choose to disable saving wh TempoSyncKnob + + Tempo Sync - + Temposynkronisering + No Sync - + Ingen synkronisering + Eight beats Åtta takter + Whole note Hel-not + Half note Halvnot + Quarter note - + Fjärdedelsnot + 8th note - + 8:e noten + 16th note - + 16:e noten + 32nd note - + 32:e noten + Custom... - + Anpassad... + Custom - + Anpassad + Synced to Eight Beats - + Synkroniserad till Åtta Takter + Synced to Whole Note - + Synkroniserad till helnoten + Synced to Half Note - + Synkroniserad till halvnoten + Synced to Quarter Note - + Synkroniserad till fjärdedelsnoten + Synced to 8th Note - + Synkroniserad till 8:e noten + Synced to 16th Note - + Synkroniserad till 16:e noten + Synced to 32nd Note - + Synkroniserad till 32:e noten TimeDisplayWidget + click to change time units Klicka för att ändra tidsenheter + MIN MIN + SEC SEK + MSEC MSEK + BAR + BEAT TAKT + TICK TICK @@ -6637,45 +8550,56 @@ Remember to also save your project manually. You can choose to disable saving wh TimeLineWidget + Enable/disable auto-scrolling - + Aktivera/inaktivera automatisk rullning + Enable/disable loop-points - + Aktivera/inaktivera loop-punkter + After stopping go back to begin - + Efter att ha stoppat gå tillbaka till början + After stopping go back to position at which playing was started - + Efter att ha stoppat gå tillbaka till position där spelningen startades + After stopping keep position - + Efter stopp behåll positionen + + Hint Ledtråd + Press <%1> to disable magnetic loop points. - + Tryck på <%1> för att inaktivera magnetiska slingpunkter. + Hold <Shift> to move the begin loop point; Press <%1> to disable magnetic loop points. - + Håll nedtryckt för att flytta startlooppunkten; tryck på <%1> för att inaktivera magnetiska slingpunkter. Track + Mute Tysta + Solo Solo @@ -6683,38 +8607,63 @@ Remember to also save your project manually. You can choose to disable saving wh TrackContainer + Couldn't import file Kunde inte importera filen + Couldn't find a filter for importing file %1. You should convert this file into a format supported by LMMS using another software. Kunde inte hitta ett filter för att importera filen %1. -Du bör konvertera filen till ett format som stöd av LMMS genom att använda ett annat program. +Du bör konvertera filen till ett format som stöds av LMMS genom att använda ett annat program. + Couldn't open file Kunde inte öppna filen + Couldn't open file %1 for reading. Please make sure you have read-permission to the file and the directory containing the file and try again! Kunde inte öppna filen %1 för läsning. -Se till att du har läsrättigheter för filen och katalogen som innehåller filen och försök igen! +Se till att du har läsrättigheter för filen och mappen som innehåller filen och försök igen! + Loading project... Läser in projekt... + + Cancel Avbryt + + Please wait... Vänligen vänta... + + Loading cancelled + Inläsningen avbruten + + + + Project loading was cancelled. + Projektinläsningen avbröts. + + + + Loading Track %1 (%2/Total %3) + Läser in spår %1 (%2/Totalt %3) + + + Importing MIDI-file... Importerar MIDI-fil... @@ -6722,6 +8671,7 @@ Se till att du har läsrättigheter för filen och katalogen som innehåller fil TrackContentObject + Mute Tysta @@ -6729,346 +8679,435 @@ Se till att du har läsrättigheter för filen och katalogen som innehåller fil TrackContentObjectView + Current position Aktuell position + + Hint Ledtråd + Press <%1> and drag to make a copy. Håll nere <%1> och dra för att kopiera. + Current length Aktuell längd + Press <%1> for free resizing. + + %1:%2 (%3:%4 to %5:%6) %1:%2 (%3:%4 till %5:%6) + Delete (middle mousebutton) Ta bort (musens mitt-knapp) + Cut Klipp ut + Copy Kopiera + Paste Klistra in + Mute/unmute (<%1> + middle click) - + Tysta/avtysta (<%1> + mittenklick) TrackOperationsWidget + Press <%1> while clicking on move-grip to begin a new drag'n'drop-action. + Actions for this track - + Åtgärder för detta spår + Mute Tysta + + Solo Solo + Mute this track Tysta detta spår + Clone this track Klona detta spår + Remove this track Ta bort detta spår + Clear this track Rensa detta spår + FX %1: %2 FX %1: %2 - Turn all recording on - - - - Turn all recording off - - - + Assign to new FX Channel Koppla till ny FX-kanal + + + Turn all recording on + Slå på all inspelning + + + + Turn all recording off + Slå av all inspelning + TripleOscillatorView + Use phase modulation for modulating oscillator 1 with oscillator 2 + Use amplitude modulation for modulating oscillator 1 with oscillator 2 + Mix output of oscillator 1 & 2 + Synchronize oscillator 1 with oscillator 2 - + Synkronisera oscillatorn 1 med oscillatorn 2 + Use frequency modulation for modulating oscillator 1 with oscillator 2 - + Använd frekvensmodulering för modulerande oscillator 1 med oscillator 2 + Use phase modulation for modulating oscillator 2 with oscillator 3 + Use amplitude modulation for modulating oscillator 2 with oscillator 3 - + Använd amplitudmodulering för modulerande oscillator 2 med oscillator 3 + Mix output of oscillator 2 & 3 + Synchronize oscillator 2 with oscillator 3 - + Synkronisera oscillatorn 2 med oscillatorn 3 + Use frequency modulation for modulating oscillator 2 with oscillator 3 + Osc %1 volume: - + Osc %1 volym: + With this knob you can set the volume of oscillator %1. When setting a value of 0 the oscillator is turned off. Otherwise you can hear the oscillator as loud as you set it here. - + Med denna knapp kan du ställa in volymen av oscillator %1. När du ställer in ett värde på 0 stängs oscillatorn av. Annars kan du höra oscillatorn så hög som du ställer in den här. + Osc %1 panning: - + Osc %1 panorering: + With this knob you can set the panning of the oscillator %1. A value of -100 means 100% left and a value of 100 moves oscillator-output right. + Osc %1 coarse detuning: + semitones halvtoner + With this knob you can set the coarse detuning of oscillator %1. You can detune the oscillator 24 semitones (2 octaves) up and down. This is useful for creating sounds with a chord. + Osc %1 fine detuning left: + + cents + With this knob you can set the fine detuning of oscillator %1 for the left channel. The fine-detuning is ranged between -100 cents and +100 cents. This is useful for creating "fat" sounds. + Osc %1 fine detuning right: + With this knob you can set the fine detuning of oscillator %1 for the right channel. The fine-detuning is ranged between -100 cents and +100 cents. This is useful for creating "fat" sounds. + Osc %1 phase-offset: + + degrees grader + With this knob you can set the phase-offset of oscillator %1. That means you can move the point within an oscillation where the oscillator begins to oscillate. For example if you have a sine-wave and have a phase-offset of 180 degrees the wave will first go down. It's the same with a square-wave. + Osc %1 stereo phase-detuning: + With this knob you can set the stereo phase-detuning of oscillator %1. The stereo phase-detuning specifies the size of the difference between the phase-offset of left and right channel. This is very good for creating wide stereo sounds. + Use a sine-wave for current oscillator. + Use a triangle-wave for current oscillator. + Use a saw-wave for current oscillator. + Use a square-wave for current oscillator. + Use a moog-like saw-wave for current oscillator. + Use an exponential wave for current oscillator. - + Använd en exponentiell våg för aktuell oscillator. + Use white-noise for current oscillator. + Use a user-defined waveform for current oscillator. - + Använd en användardefinierad vågform för nuvarande oscillator. VersionedSaveDialog + Increment version number + Decrement version number + already exists. Do you want to replace it? - + finns redan. Vill du ersätta den? VestigeInstrumentView + Open other VST-plugin + Click here, if you want to open another VST-plugin. After clicking on this button, a file-open-dialog appears and you can select your file. - Show/hide GUI - Visa/dölj användargränssnitt - - - Click here to show or hide the graphical user interface (GUI) of your VST-plugin. - - - - Turn off all notes - - - - Open VST-plugin - Öppna VST-plugin - - - DLL-files (*.dll) - DLL-filer (*.dll) - - - EXE-files (*.exe) - EXE-filer (*.exe) - - - No VST-plugin loaded - - - + Control VST-plugin from LMMS host - Kontrollera VST-plugin från LMMS-värd + Kontrollera VST-insticksmodulen från LMMS-värd + Click here, if you want to control VST-plugin from host. - + Klicka här om du vill styra VST-insticksmodulen från värd. + Open VST-plugin preset + Click here, if you want to open another *.fxp, *.fxb VST-plugin preset. - + Klicka här om du vill öppna en annan *.fxp, *.FXB VST-insticksmodulsförinställning. + Previous (-) Tidigare (-) + + Click here, if you want to switch to another VST-plugin preset program. - + Klicka här om du vill byta till ett annat VST-insticksmodulsförinställningsprogram. + Save preset Spara förinställning + Click here, if you want to save current VST-plugin preset program. + Next (+) Nästa (+) + Click here to select presets that are currently loaded in VST. + + Show/hide GUI + Visa/dölj användargränssnitt + + + + Click here to show or hide the graphical user interface (GUI) of your VST-plugin. + + + + + Turn off all notes + Stäng av alla noter + + + + Open VST-plugin + Öppna VST-insticksmodul + + + + DLL-files (*.dll) + DLL-filer (*.dll) + + + + EXE-files (*.exe) + EXE-filer (*.exe) + + + + No VST-plugin loaded + Ingen VST-insticksmodul inläst + + + Preset Förinställning + by av + - VST plugin control @@ -7076,10 +9115,12 @@ Se till att du har läsrättigheter för filen och katalogen som innehåller fil VisualizationWidget + click to enable/disable visualization of master-output + Click to enable Klicka för att aktivera @@ -7087,54 +9128,69 @@ Se till att du har läsrättigheter för filen och katalogen som innehåller fil VstEffectControlDialog + Show/hide Visa/dölj + Control VST-plugin from LMMS host Kontrollera VST-plugin från LMMS-värd + Click here, if you want to control VST-plugin from host. - + Klicka här om du vill styra VST-insticksmodulen från värd. + Open VST-plugin preset + Click here, if you want to open another *.fxp, *.fxb VST-plugin preset. - + Klicka här om du vill öppna en annan *.fxp, *.fxb VST-insticksmodulsförinställning. + Previous (-) Tidigare (-) + + Click here, if you want to switch to another VST-plugin preset program. - + Klicka här om du vill byta till ett annat VST-insticksmodulsförinställningsprogram. + Next (+) Nästa (+) + Click here to select presets that are currently loaded in VST. + Save preset Spara förinställning + Click here, if you want to save current VST-plugin preset program. + + Effect by: Effekt skapad av: + &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /> @@ -7142,387 +9198,509 @@ Se till att du har läsrättigheter för filen och katalogen som innehåller fil VstPlugin - Loading plugin - Laddar plugin + + + The VST plugin %1 could not be loaded. + VST-insticksmodulen %1 kunde inte läsas in. + Open Preset Öppna Förinställning + + Vst Plugin Preset (*.fxp *.fxb) + : default : standard + " " + ' ' + Save Preset Spara Förinställning + .fxp .fxp + .FXP .FXP + .FXB .FXB + .fxb .fxb - Please wait while loading VST plugin... - Vänta medan VST-plugin läses in... + + Loading plugin + Läser in insticksmodulen - The VST plugin %1 could not be loaded. - + + Please wait while loading VST plugin... + Vänligen vänta medan VST-instickmodulen läses in... WatsynInstrument + Volume A1 Volym A1 + Volume A2 Volym A2 + Volume B1 Volym B2 + Volume B2 Volym B2 + Panning A1 - + Panorering A1 + Panning A2 - + Panorering A2 + Panning B1 - + Panorering B1 + Panning B2 - + Panorering B2 + Freq. multiplier A1 + Freq. multiplier A2 + Freq. multiplier B1 + Freq. multiplier B2 + Left detune A1 + Left detune A2 + Left detune B1 + Left detune B2 + Right detune A1 + Right detune A2 + Right detune B1 + Right detune B2 + A-B Mix + A-B Mix envelope amount + A-B Mix envelope attack + A-B Mix envelope hold + A-B Mix envelope decay + A1-B2 Crosstalk + A2-A1 modulation - + A2-A1 modulering + B2-B1 modulation - + B2-B1 modulering + Selected graph - + Vald graf WatsynView - Select oscillator A1 - - - - Select oscillator A2 - - - - Select oscillator B1 - - - - Select oscillator B2 - - - - Mix output of A2 to A1 - - - - Modulate amplitude of A1 with output of A2 - - - - Ring-modulate A1 and A2 - - - - Modulate phase of A1 with output of A2 - - - - Mix output of B2 to B1 - - - - Modulate amplitude of B1 with output of B2 - - - - Ring-modulate B1 and B2 - - - - Modulate phase of B1 with output of B2 - - - - Draw your own waveform here by dragging your mouse on this graph. - - - - Load waveform - Ladda vågform - - - Click to load a waveform from a sample file - Klicka för att ladda in en vågform från en ljudfil - - - Phase left - - - - Click to shift phase by -15 degrees - - - - Phase right - - - - Click to shift phase by +15 degrees - - - - Normalize - Normalisera - - - Click to normalize - Klicka för normalisering - - - Invert - Invertera - - - Click to invert - Klicka för invertering - - - Smooth - Utjämna - - - Click to smooth - Klicka för utjämning - - - Sine wave - Sinusvåg - - - Click for sine wave - Klicka för sinusvåg - - - Triangle wave - Triangelvåg - - - Click for triangle wave - Klicka för triangelvåg - - - Click for saw wave - Klicka för sågtandvåg - - - Square wave - Fyrkantvåg - - - Click for square wave - - - + + + + Volume Volym + + + + Panning Panorering + + + + Freq. multiplier + + + + Left detune + + + + + + + + cents + + + + Right detune + A-B Mix + Mix envelope amount + Mix envelope attack + Mix envelope hold + Mix envelope decay + Crosstalk + + + Select oscillator A1 + Välj oscillator A1 + + + + Select oscillator A2 + Välj oscillator A2 + + + + Select oscillator B1 + Välj oscillator B1 + + + + Select oscillator B2 + Välj oscillator B2 + + + + Mix output of A2 to A1 + + + + + Modulate amplitude of A1 with output of A2 + + + + + Ring-modulate A1 and A2 + + + + + Modulate phase of A1 with output of A2 + + + + + Mix output of B2 to B1 + Blanda utgång B2 till B1 + + + + Modulate amplitude of B1 with output of B2 + + + + + Ring-modulate B1 and B2 + + + + + Modulate phase of B1 with output of B2 + + + + + + + + Draw your own waveform here by dragging your mouse on this graph. + Rita din egen vågform här genom att dra musen på den här grafen. + + + + Load waveform + Ladda vågform + + + + Click to load a waveform from a sample file + Klicka för att ladda in en vågform från en ljudfil + + + + Phase left + Fas vänster + + + + Click to shift phase by -15 degrees + Klicka för att flytta fas med -15 grader + + + + Phase right + Fas höger + + + + Click to shift phase by +15 degrees + + + + + Normalize + Normalisera + + + + Click to normalize + Klicka för normalisering + + + + Invert + Invertera + + + + Click to invert + Klicka för invertering + + + + Smooth + Utjämna + + + + Click to smooth + Klicka för utjämning + + + + Sine wave + Sinusvåg + + + + Click for sine wave + Klicka för sinusvåg + + + + + Triangle wave + Triangelvåg + + + + Click for triangle wave + Klicka för triangelvåg + + + + Click for saw wave + Klicka för sågtandsvåg + + + + Square wave + Fyrkantvåg + + + + Click for square wave + Klicka för fyrkantvåg + ZynAddSubFxInstrument + Portamento + Filter Frequency + Filter Resonance + Bandwidth Bandbredd + FM Gain FM-Förstärkning + Resonance Center Frequency + Resonance Bandwidth - + Resonans Bandbredd + Forward MIDI Control Change Events @@ -7530,121 +9708,150 @@ Se till att du har läsrättigheter för filen och katalogen som innehåller fil ZynAddSubFxView - Show GUI - Visa användargränssnitt - - - Click here to show or hide the graphical user interface (GUI) of ZynAddSubFX. - Klicka här för att visa eller dölja användargränssnittet för ZynAddSubFX. - - + Portamento: Portamento: + PORT - + PORT + Filter Frequency: Filter-frekvens: + FREQ FREQ + Filter Resonance: Filter-resonans: + RES + Bandwidth: Bandbredd: + BW + FM Gain: FM-Förstärkning: + FM GAIN + Resonance center frequency: - + Resonanscenterfrekvens: + RES CF + Resonance bandwidth: - + Resonans bandbredd: + RES BW + Forward MIDI Control Changes + + + Show GUI + Visa användargränssnitt + + + + Click here to show or hide the graphical user interface (GUI) of ZynAddSubFX. + Klicka här för att visa eller dölja användargränssnittet för ZynAddSubFX. + audioFileProcessor + Amplify Amplifiera + Start of sample Start på ljudfil + End of sample Slut på ljudfil + + Loopback point + Loopback punkt + + + Reverse sample Spela baklänges - Stutter - - - - Loopback point - - - + Loop mode - + Slinga-läge + + Stutter + Stamning + + + Interpolation mode - + Interpoleringsläge + None - + Ingen + Linear Linjär + Sinc + Sample not found: %1 Ljudfil hittades inte: %1 @@ -7652,6 +9859,7 @@ Se till att du har läsrättigheter för filen och katalogen som innehåller fil bitInvader + Samplelength Ljudfilslängd @@ -7659,165 +9867,205 @@ Se till att du har läsrättigheter för filen och katalogen som innehåller fil bitInvaderView + Sample Length Ljudfilens Längd + + Draw your own waveform here by dragging your mouse on this graph. + Rita din egen vågform här genom att dra musen på den här grafen. + + + Sine wave Sinusvåg - Triangle wave - Triangelvåg - - - Saw wave - Sågtandsvåg - - - Square wave - Fyrkantvåg - - - White noise wave - Vitt brus-våg - - - User defined wave - Användardefinierad vågform - - - Smooth - Utjämna - - - Click here to smooth waveform. - - - - Interpolation - Interpolering - - - Normalize - Normalisera - - - Draw your own waveform here by dragging your mouse on this graph. - - - + Click for a sine-wave. Klicka för sinusvåg + + Triangle wave + Triangelvåg + + + Click here for a triangle-wave. Klicka här för triangelvåg. + + Saw wave + Sågtandsvåg + + + Click here for a saw-wave. - Klicka här för sågtandvåg + Klicka här för sågtandsvåg + + Square wave + Fyrkantvåg + + + Click here for a square-wave. - Klicka här för fyrkantvåg + Klicka här för fyrkantvåg. + + White noise wave + Vitt brus-våg + + + Click here for white-noise. Klicka här för vitt brus. + + User defined wave + Användardefinierad vågform + + + Click here for a user-defined shape. Klicka här för en användardefinierad kurva. + + + Smooth + Utjämna + + + + Click here to smooth waveform. + Klicka här för att jämna vågform. + + + + Interpolation + Interpolering + + + + Normalize + Normalisera + dynProcControlDialog + INPUT INGÅNG + Input gain: Ingångsförstärkning: + OUTPUT UTGÅNG + Output gain: Utgångsförstärkning: + ATTACK - + ATTACK + Peak attack time: + RELEASE + Peak release time: + Reset waveform Återställ vågform + Click here to reset the wavegraph back to default + Smooth waveform Mjuk vågform + Click here to apply smoothing to wavegraph + Increase wavegraph amplitude by 1dB + Click here to increase wavegraph amplitude by 1dB - + Klicka här för att öka våggrafamplituden med 1 dB + Decrease wavegraph amplitude by 1dB - + Minska våggrafamplituden med 1dB + Click here to decrease wavegraph amplitude by 1dB + Stereomode Maximum + Process based on the maximum of both stereo channels + Stereomode Average + Process based on the average of both stereo channels + Stereomode Unlinked + Process each stereo channel independently @@ -7825,22 +10073,27 @@ Se till att du har läsrättigheter för filen och katalogen som innehåller fil dynProcControls + Input gain Ingångsförstärkning + Output gain Utgångsförstärkning + Attack time - + Attacktid + Release time + Stereo mode Stereo-läge @@ -7848,10 +10101,12 @@ Se till att du har läsrättigheter för filen och katalogen som innehåller fil fxLineLcdSpinBox + Assign to: Tilldela till: + New FX Channel Ny FX-Kanal @@ -7859,6 +10114,7 @@ Se till att du har läsrättigheter för filen och katalogen som innehåller fil graphModel + Graph Graf @@ -7866,93 +10122,115 @@ Se till att du har läsrättigheter för filen och katalogen som innehåller fil kickerInstrument + Start frequency Startfrekvens + End frequency Slutfrekvens - Gain - Förstärkning - - + Length Längd + Distortion Start + Distortion End + + Gain + Förstärkning + + + Envelope Slope + Noise Brus + Click Klick + Frequency Slope + Start from note - + Starta från not + End to note - + Sluta på not kickerInstrumentView + Start frequency: - + Startfrekvens: + End frequency: - - - - Gain: - Förstärkning: + Slutfrekvens: + Frequency Slope: + + Gain: + Förstärkning: + + + Envelope Length: + Envelope Slope: + Click: Klick: + Noise: Brus: + Distortion Start: + Distortion End: @@ -7960,26 +10238,37 @@ Se till att du har läsrättigheter för filen och katalogen som innehåller fil ladspaBrowserView + + Available Effects - + Tillgängliga effekter + + Unavailable Effects - + Otillgängliga effekter + + Instruments Instrument + + Analysis Tools Analysverktyg + + Don't know Vet inte + This dialog displays information on all of the LADSPA plugins LMMS was able to locate. The plugins are divided into five categories based upon an interpretation of the port types and names. Available Effects are those that can be used by LMMS. In order for LMMS to be able to use an effect, it must, first and foremost, be an effect, which is to say, it has to have both input channels and output channels. LMMS identifies an input channel as an audio rate port containing 'in' in the name. Output channels are identified by the letters 'out'. Furthermore, the effect must have the same number of inputs and outputs and be real time capable. @@ -7996,6 +10285,7 @@ Double clicking any of the plugins will bring up information on the ports. + Type: Typ: @@ -8003,10 +10293,12 @@ Double clicking any of the plugins will bring up information on the ports. ladspaDescription + Plugins - Plugin + Insticksmoduler + Description Beskrivning @@ -8014,66 +10306,83 @@ Double clicking any of the plugins will bring up information on the ports. ladspaPortDialog + Ports Portar + Name Namn + Rate Värdera + Direction Riktning + Type Typ + Min < Default < Max Min < Standard < Max + Logarithmic Logaritmisk + SR Dependent + Audio Ljud + Control Kontroll + Input Ingång + Output Utgång + Toggled - + Växlad + Integer Heltal + Float Flyttal + + Yes Ja @@ -8081,46 +10390,57 @@ Double clicking any of the plugins will bring up information on the ports. lb302Synth + VCF Cutoff Frequency + VCF Resonance + VCF Envelope Mod + VCF Envelope Decay + Distortion - + Förvrängning + Waveform Vågform + Slide Decay + Slide + Accent + Dead + 24dB/oct Filter @@ -8128,122 +10448,153 @@ Double clicking any of the plugins will bring up information on the ports. lb302SynthView + Cutoff Freq: + Resonance: Resonans: + Env Mod: + Decay: Decay: + 303-es-que, 24dB/octave, 3 pole filter + Slide Decay: + DIST: + Saw wave Sågtandsvåg + Click here for a saw-wave. - Klicka här för sågtandvåg + Klicka här för sågtandsvåg + Triangle wave Triangelvåg + Click here for a triangle-wave. Klicka här för triangelvåg. + Square wave Fyrkantvåg + Click here for a square-wave. Klicka här för fyrkantvåg + Rounded square wave + Click here for a square-wave with a rounded end. + Moog wave + Click here for a moog-like wave. + Sine wave Sinusvåg + Click for a sine-wave. Klicka för sinusvåg + + White noise wave Vitt brus-våg + Click here for an exponential wave. + Click here for white-noise. Klicka här för vitt brus. + Bandlimited saw wave + Click here for bandlimited saw wave. + Bandlimited square wave + Click here for bandlimited square wave. + Bandlimited triangle wave + Click here for bandlimited triangle wave. + Bandlimited moog saw wave + Click here for bandlimited moog saw wave. @@ -8251,268 +10602,334 @@ Double clicking any of the plugins will bring up information on the ports. malletsInstrument + Hardness - + Hårdhet + Position Position + Vibrato Gain + Vibrato Freq + Stick Mix + Modulator - + Modulator + Crossfade - + Överbländning + LFO Speed - + LFO hastighet + LFO Depth + ADSR - + ADSR + Pressure - + Tryck + Motion - + Rörelse + Speed Hastighet + Bowed + Spread + Marimba + Vibraphone + Agogo + Wood1 + Reso + Wood2 + Beats - + Takter + Two Fixed + Clump + Tubular Bells + Uniform Bar + Tuned Bar + Glass + Tibetan Bowl - + Tibetansk skål malletsInstrumentView + Instrument - + Instrument + Spread + Spread: + + Missing files + Saknade filer + + + + Your Stk-installation seems to be incomplete. Please make sure the full Stk-package is installed! + Din Stk-installation verkar vara ofullständig. Se till att hela Stk-paketet är installerat! + + + Hardness - + Hårdhet + Hardness: - + Hårdhet: + Position Position + Position: Position: + Vib Gain + Vib Gain: + Vib Freq + Vib Freq: + Stick Mix + Stick Mix: + Modulator - + Modulator + Modulator: - + Modulator: + Crossfade - + Överbländning + Crossfade: - + Överbländning: + LFO Speed - + LFO hastighet + LFO Speed: + LFO Depth + LFO Depth: + ADSR - + ADSR + ADSR: - + ADSR: + Pressure - + Tryck + Pressure: - + Tryck: + Speed Hastighet + Speed: Hastighet: - - Missing files - - - - Your Stk-installation seems to be incomplete. Please make sure the full Stk-package is installed! - - manageVSTEffectView + - VST parameter control + VST Sync + Click here if you want to synchronize all parameters with VST plugin. + + Automated Automatiserad + Click here if you want to display automated parameters only. - + Klicka här om du bara vill visa automatiska parametrar. + Close Stäng + Close VST effect knob-controller window. @@ -8520,30 +10937,39 @@ Double clicking any of the plugins will bring up information on the ports. manageVestigeInstrumentView + + - VST plugin control + VST Sync + Click here if you want to synchronize all parameters with VST plugin. + + Automated Automatiserad + Click here if you want to display automated parameters only. - + Klicka här om du bara vill visa automatiserade parametrar. + Close Stäng + Close VST plugin knob-controller window. @@ -8551,118 +10977,147 @@ Double clicking any of the plugins will bring up information on the ports. opl2instrument + Patch + Op 1 Attack + Op 1 Decay + Op 1 Sustain + Op 1 Release + Op 1 Level + Op 1 Level Scaling + Op 1 Frequency Multiple + Op 1 Feedback + Op 1 Key Scaling Rate + Op 1 Percussive Envelope + Op 1 Tremolo + Op 1 Vibrato + Op 1 Waveform + Op 2 Attack + Op 2 Decay + Op 2 Sustain + Op 2 Release + Op 2 Level + Op 2 Level Scaling + Op 2 Frequency Multiple + Op 2 Key Scaling Rate + Op 2 Percussive Envelope + Op 2 Tremolo + Op 2 Vibrato + Op 2 Waveform + FM FM + Vibrato Depth + Tremolo Depth @@ -8670,18 +11125,26 @@ Double clicking any of the plugins will bring up information on the ports. opl2instrumentView + + Attack Attack + + Decay Decay + + Release - Släpp + Release + + Frequency multiplier @@ -8689,10 +11152,12 @@ Double clicking any of the plugins will bring up information on the ports. organicInstrument + Distortion - + Förvrängning + Volume Volym @@ -8700,351 +11165,458 @@ Double clicking any of the plugins will bring up information on the ports. organicInstrumentView + Distortion: - - - - Volume: - Volym: - - - Randomise - Slumpa - - - Osc %1 waveform: - - - - Osc %1 volume: - - - - Osc %1 panning: - - - - cents - + Förvrängning: + The distortion knob adds distortion to the output of the instrument. + + Volume: + Volym: + + + The volume knob controls the volume of the output of the instrument. It is cumulative with the instrument window's volume control. + + Randomise + Slumpa + + + The randomize button randomizes all knobs except the harmonics,main volume and distortion knobs. + Knappen randomisera randomiserar alla rattar utom reglagen övertoner, huvudvolym och distorsion. + + + + + Osc %1 waveform: + + Osc %1 volume: + Osc %1 volym: + + + + Osc %1 panning: + Osc %1 panorering: + + + Osc %1 stereo detuning - Osc %1 harmonic: + + cents + + + Osc %1 harmonic: + Osc %1 harmonisk: + FreeBoyInstrument + Sweep time + Sweep direction + Sweep RtShift amount + + Wave Pattern Duty + Channel 1 volume - + Kanal 1 volym + + + Volume sweep direction + + + Length of each step in sweep + Channel 2 volume - + Kanal 2 volym + Channel 3 volume - + Kanal 3 volym + Channel 4 volume + Kanal 4 volym + + + + Shift Register width + Right Output level + Left Output level + Channel 1 to SO2 (Left) - + Kanal 1 till SO2 (vänster) + Channel 2 to SO2 (Left) - + Kanal 2 till SO2 (vänster) + Channel 3 to SO2 (Left) - + Kanal 3 till SO2 (vänster) + Channel 4 to SO2 (Left) - + Kanal 4 till SO2 (Vänster) + Channel 1 to SO1 (Right) - + Kanal 1 till SO1 (Höger) + Channel 2 to SO1 (Right) - + Kanal 2 till SO1 (höger) + Channel 3 to SO1 (Right) - + Kanal 3 till SO1 (höger) + Channel 4 to SO1 (Right) - + Kanal 4 till SO1 (höger) + Treble - + Diskant + Bass Bas - - Shift Register width - - FreeBoyInstrumentView + Sweep Time: + Sweep Time + + The amount of increase or decrease in frequency + Mängden ökning eller minskning av frekvensen + + + Sweep RtShift amount: + Sweep RtShift amount - Wave pattern duty: - - - - Wave Pattern Duty - - - - Square Channel 1 Volume: - - - - Length of each step in sweep: - - - - Length of each step in sweep - - - - Wave pattern duty - - - - Square Channel 2 Volume: - - - - Square Channel 2 Volume - - - - Wave Channel Volume: - - - - Wave Channel Volume - - - - Noise Channel Volume: - - - - Noise Channel Volume - - - - SO1 Volume (Right): - - - - SO1 Volume (Right) - - - - SO2 Volume (Left): - - - - SO2 Volume (Left) - - - - Treble: - - - - Treble - - - - Bass: - Bas: - - - Bass - Bas - - - Sweep Direction - - - - Volume Sweep Direction - - - - Shift Register Width - - - - Channel1 to SO1 (Right) - - - - Channel2 to SO1 (Right) - - - - Channel3 to SO1 (Right) - - - - Channel4 to SO1 (Right) - - - - Channel1 to SO2 (Left) - - - - Channel2 to SO2 (Left) - - - - Channel3 to SO2 (Left) - - - - Channel4 to SO2 (Left) - - - - Wave Pattern - - - - The amount of increase or decrease in frequency - - - + The rate at which increase or decrease in frequency occurs + + + Wave pattern duty: + + + + + Wave Pattern Duty + + + + + The duty cycle is the ratio of the duration (time) that a signal is ON versus the total period of the signal. + + + Square Channel 1 Volume: + + + + Square Channel 1 Volume + + + + Length of each step in sweep: + + + + + + + Length of each step in sweep + + + + + + The delay between step change - Draw the wave here + + Wave pattern duty + + + Square Channel 2 Volume: + + + + + + Square Channel 2 Volume + + + + + Wave Channel Volume: + + + + + + Wave Channel Volume + Volym för vågkanalen + + + + Noise Channel Volume: + + + + + + Noise Channel Volume + + + + + SO1 Volume (Right): + SO1 volym (höger): + + + + SO1 Volume (Right) + + + + + SO2 Volume (Left): + SO2 volym (vänster): + + + + SO2 Volume (Left) + + + + + Treble: + Diskant: + + + + Treble + Diskant + + + + Bass: + Bas: + + + + Bass + Bas + + + + Sweep Direction + + + + + + + + + Volume Sweep Direction + + + + + Shift Register Width + + + + + Channel1 to SO1 (Right) + + + + + Channel2 to SO1 (Right) + Channel2 till SO1 (höger) + + + + Channel3 to SO1 (Right) + + + + + Channel4 to SO1 (Right) + Channel4 till SO1 (höger) + + + + Channel1 to SO2 (Left) + + + + + Channel2 to SO2 (Left) + Channel2 till SO2 (Vänster) + + + + Channel3 to SO2 (Left) + Channel3 till SO2 (vänster) + + + + Channel4 to SO2 (Left) + + + + + Wave Pattern + Vågmönster + + + + Draw the wave here + Rita vågen här + patchesDialog + Qsynth: Channel Preset - + Qsynth: Kanal förinställd + Bank selector - + Bankväljare + Bank Bank + Program selector - + Programväljare + Patch + Name Namn + OK OK + Cancel Avbryt @@ -9052,238 +11624,301 @@ Double clicking any of the plugins will bring up information on the ports. pluginBrowser + no description ingen beskrivning - Incomplete monophonic imitation tb303 + + A native amplifier plugin + En inbyggd förstärkare-insticksmodul + + + + Simple sampler with various settings for using samples (e.g. drums) in an instrument-track + Enkel sampler med olika inställningar för att använda samplingar (t. ex. trummor) i ett instrumentspår + + + + Boost your bass the fast and simple way + Öka din bas på snabbt och enkelt sätt + + + + Customizable wavetable synthesizer - Plugin for freely manipulating stereo output + + An oversampling bitcrusher - Plugin for controlling knobs with sound peaks + + Carla Patchbay Instrument - Plugin for enhancing stereo separation of a stereo input file + + Carla Rack Instrument + + A 4-band Crossover Equalizer + + + + + A native delay plugin + En inbyggd fördröjning-insticksmodul + + + + A Dual filter plugin + En Dual filter-insticksmodul + + + + plugin for processing dynamics in a flexible way + insticksmodul för dynamisk bearbetning på ett flexibelt sätt + + + + A native eq plugin + En inbyggd eq-insticksmodul + + + + A native flanger plugin + + + + + Player for GIG files + Spelare för GIG-filer + + + + Filter for importing Hydrogen files into LMMS + Filter för att importera Hydrogen-filer till LMMS + + + + Versatile drum synthesizer + Mångsidig trum-synth + + + List installed LADSPA plugins - - - - GUS-compatible patch instrument - - - - Additive Synthesizer for organ-like sounds - - - - Tuneful things to bang on - - - - VST-host for using VST(i)-plugins within LMMS - - - - Vibrating string modeler - + Lista installerade LADSPA-insticksmoduler + plugin for using arbitrary LADSPA-effects inside LMMS. + + Incomplete monophonic imitation tb303 + + + + + Filter for exporting MIDI-files from LMMS + Filter för att exportera MIDI-filer från LMMS + + + Filter for importing MIDI-files into LMMS Filter för att importera MIDI-filer till LMMS + + Monstrous 3-oscillator synth with modulation matrix + + + + + A multitap echo delay plugin + + + + + A NES-like synthesizer + En NES-lik synthesizer + + + + 2-operator FM Synth + + + + + Additive Synthesizer for organ-like sounds + + + + + Emulation of GameBoy (TM) APU + Emulering av GameBoy (TM) APU + + + + GUS-compatible patch instrument + + + + + Plugin for controlling knobs with sound peaks + + + + + Reverb algorithm by Sean Costello + + + + + Player for SoundFont files + Spelare för SoundFont-filer + + + + LMMS port of sfxr + + + + Emulation of the MOS6581 and MOS8580 SID. This chip was used in the Commodore 64 computer. - Player for SoundFont files - Spelare för SoundFont-filer + + Graphical spectrum analyzer plugin + Grafiska spektrumanalysator insticksmodul - Emulation of GameBoy (TM) APU - Emulering av GameBoy (TM) APU + + Plugin for enhancing stereo separation of a stereo input file + Insticksmodul för att förbättra stereoseparation av en stereoingångsfil - Customizable wavetable synthesizer + + Plugin for freely manipulating stereo output - Embedded ZynAddSubFX - - - - 2-operator FM Synth - - - - Filter for importing Hydrogen files into LMMS - Filter för att importera Hydrogen-filer till LMMS - - - LMMS port of sfxr - - - - Monstrous 3-oscillator synth with modulation matrix + + Tuneful things to bang on + Three powerful oscillators you can modulate in several ways - A native amplifier plugin + + VST-host for using VST(i)-plugins within LMMS - Carla Rack Instrument - - - - 4-oscillator modulatable wavetable synth - - - - plugin for waveshaping - - - - Boost your bass the fast and simple way - - - - Versatile drum synthesizer - Mångsidig trum-synth - - - Simple sampler with various settings for using samples (e.g. drums) in an instrument-track - - - - plugin for processing dynamics in a flexible way - - - - Carla Patchbay Instrument + + Vibrating string modeler + plugin for using arbitrary VST effects inside LMMS. - Graphical spectrum analyzer plugin + + 4-oscillator modulatable wavetable synth - A NES-like synthesizer - En NES-lik synthesizer + + plugin for waveshaping + insticksmodul för vågformande - A native delay plugin - - - - Player for GIG files - Spelare för GIG-filer - - - A multitap echo delay plugin - - - - A native flanger plugin - - - - An oversampling bitcrusher - - - - A native eq plugin - - - - A 4-band Crossover Equalizer - - - - A Dual filter plugin - - - - Filter for exporting MIDI-files from LMMS + + Embedded ZynAddSubFX sf2Instrument + Bank Bank + Patch + Gain Förstärkning + Reverb - + Reverb + Reverb Roomsize + Reverb Damping + Reverb Width + Reverb Level + Chorus - + Chorus + Chorus Lines + Chorus Level + Chorus Speed + Chorus Depth + A soundfont %1 could not be loaded. SoundFont %1 kunde inte läsas in. @@ -9291,74 +11926,92 @@ This chip was used in the Commodore 64 computer. sf2InstrumentView + Open other SoundFont file Öppna en annan SoundFont-fil + Click here to open another SF2 file Klicka här för att öppna en annan SF2-fil + Choose the patch + Gain Förstärkning + Apply reverb (if supported) - + Applicera reverb (om det stöds) + This button enables the reverb effect. This is useful for cool effects, but only works on files that support it. - + Denna knapp aktiverar reverb-effekten. Detta är användbart för häftiga effekter, men fungerar bara på filer som stöder den. + Reverb Roomsize: + Reverb Damping: + Reverb Width: + Reverb Level: + Apply chorus (if supported) - + Applicera chorus (om det stöds) + This button enables the chorus effect. This is useful for cool echo effects, but only works on files that support it. - + Denna knapp aktiverar köreffekten. Detta är användbart för coola eko effekter, men fungerar bara på filer som stöder den. + Chorus Lines: + Chorus Level: + Chorus Speed: + Chorus Depth: + Open SoundFont file - + Öppna SoundFont-fil + SoundFont2 Files (*.sf2) SoundFont2-filer (*.sf2) @@ -9366,6 +12019,7 @@ This chip was used in the Commodore 64 computer. sfxrInstrument + Wave Form Vågform @@ -9373,26 +12027,32 @@ This chip was used in the Commodore 64 computer. sidInstrument + Cutoff + Resonance Resonans + Filter type Filtertyp + Voice 3 off - + Röst 3 av + Volume Volym + Chip model @@ -9400,134 +12060,172 @@ This chip was used in the Commodore 64 computer. sidInstrumentView + Volume: Volym: + Resonance: Resonans: + + Cutoff frequency: + High-Pass filter Högpassfilter + Band-Pass filter Bandpassfilter + Low-Pass filter Lågpassfilter + Voice3 Off - + Voice3 Av + MOS6581 SID MOS6581 SID + MOS8580 SID MOS8580 SID + + Attack: Attack: + Attack rate determines how rapidly the output of Voice %1 rises from zero to peak amplitude. - + Attack-hastigheten bestämmer hur snabbt utgången för Voice %1 stiger från noll till toppamplitud. + + Decay: Decay: + Decay rate determines how rapidly the output falls from the peak amplitude to the selected Sustain level. + Sustain: Sustain: + Output of Voice %1 will remain at the selected Sustain amplitude as long as the note is held. + + Release: Release: + The output of of Voice %1 will fall from Sustain amplitude to zero amplitude at the selected Release rate. + + Pulse Width: Pulsbredd: + The Pulse Width resolution allows the width to be smoothly swept with no discernable stepping. The Pulse waveform on Oscillator %1 must be selected to have any audible effect. + Coarse: Grov: + The Coarse detuning allows to detune Voice %1 one octave up or down. - + Den grova detuningen gör det möjligt att detunera Voice %1 en oktav upp eller ner. + Pulse Wave Pulsvåg + Triangle Wave Triangelvåg + SawTooth Sågtand + Noise Brus + Sync - + Synkronisera + Sync synchronizes the fundamental frequency of Oscillator %1 with the fundamental frequency of Oscillator %2 producing "Hard Sync" effects. + Ring-Mod + Ring-mod replaces the Triangle Waveform output of Oscillator %1 with a "Ring Modulated" combination of Oscillators %1 and %2. + Filtered Filtrerad + When Filtered is on, Voice %1 will be processed through the Filter. When Filtered is off, Voice %1 appears directly at the output, and the Filter has no effect on it. + Test Testa + Test, when set, resets and locks Oscillator %1 at zero until Test is turned off. @@ -9535,10 +12233,12 @@ This chip was used in the Commodore 64 computer. stereoEnhancerControlDialog + WIDE + Width: Bredd: @@ -9546,6 +12246,7 @@ This chip was used in the Commodore 64 computer. stereoEnhancerControls + Width Bredd @@ -9553,91 +12254,111 @@ This chip was used in the Commodore 64 computer. stereoMatrixControlDialog + Left to Left Vol: Vänster till Vänster Vol.: + Left to Right Vol: Vänster till Höger Vol.: + Right to Left Vol: Höger till Vänster Vol.: + Right to Right Vol: - + Höger till Höger vol.: stereoMatrixControls + Left to Left - Vänster till vänster + Vänster till Vänster + Left to Right - Vänster till höger + Vänster till Höger + Right to Left - Höger till vänster + Höger till Vänster + Right to Right - Höger till höger + Höger till Höger vestigeInstrument + Loading plugin - Laddar plugin + Läser in plugin + Please wait while loading VST-plugin... - Vänta medans VST-plugin läses in... + Vänta medans VST-insticksmodulen läses in... vibed + String %1 volume - + Sträng %1 volym + String %1 stiffness - + Sträng %1 styvhet + Pick %1 position - + Välj %1 position + Pickup %1 position + Pan %1 + Detune %1 + Fuzziness %1 - + Oskärpa %1  + Length %1 Längd %1 + Impulse %1 Impuls %1 + Octave %1 Oktav %1 @@ -9645,90 +12366,112 @@ This chip was used in the Commodore 64 computer. vibedView + Volume: Volym: + The 'V' knob sets the volume of the selected string. + String stiffness: - + Strängstyvhet: + The 'S' knob sets the stiffness of the selected string. The stiffness of the string affects how long the string will ring out. The lower the setting, the longer the string will ring. + Pick position: + The 'P' knob sets the position where the selected string will be 'picked'. The lower the setting the closer the pick is to the bridge. - + "P" - ratten ställer in den position där den valda strängen kommer att "plockas". Ju lägre inställningen desto närmare plockningen är till bridgen. + Pickup position: + The 'PU' knob sets the position where the vibrations will be monitored for the selected string. The lower the setting, the closer the pickup is to the bridge. + Pan: + The Pan knob determines the location of the selected string in the stereo field. + Detune: + The Detune knob modifies the pitch of the selected string. Settings less than zero will cause the string to sound flat. Settings greater than zero will cause the string to sound sharp. + Fuzziness: - + Oskärpa: + The Slap knob adds a bit of fuzz to the selected string which is most apparent during the attack, though it can also be used to make the string sound more 'metallic'. + Length: Längd: + The Length knob sets the length of the selected string. Longer strings will both ring longer and sound brighter, however, they will also eat up more CPU cycles. + Impulse or initial state + The 'Imp' selector determines whether the waveform in the graph is to be treated as an impulse imparted to the string by the pick or the initial state of the string. + Octave Oktav + The Octave selector is used to choose which harmonic of the note the string will ring at. For example, '-2' means the string will ring two octaves below the fundamental, 'F' means the string will ring at the fundamental, and '6' means the string will ring six octaves above the fundamental. + Impulse Editor + The waveform editor provides control over the initial state or impulse that is used to start the string vibrating. The buttons to the right of the graph will initialize the waveform to the selected type. The '?' button will load a waveform from a file--only the first 128 samples will be loaded. The waveform can also be drawn in the graph. @@ -9739,6 +12482,7 @@ The 'N' button will normalize the waveform. + Vibed models up to nine independently vibrating strings. The 'String' selector allows you to choose which string is being edited. The 'Imp' selector chooses whether the graph represents an impulse or the initial state of the string. The 'Octave' selector chooses which harmonic the string should vibrate at. The graph allows you to control the initial state or impulse used to set the string in motion. @@ -9753,188 +12497,233 @@ The LED in the lower right corner of the waveform editor determines whether the + Enable waveform - + Aktivera vågform + Click here to enable/disable waveform. - + Klicka här för att aktivera/inaktivera vågform. + String Sträng + The String selector is used to choose which string the controls are editing. A Vibed instrument can contain up to nine independently vibrating strings. The LED in the lower right corner of the waveform editor indicates whether the selected string is active. + Sine wave Sinusvåg - Triangle wave - Triangelvåg - - - Saw wave - Sågtandsvåg - - - Square wave - Fyrkantvåg - - - White noise wave - Vitt brus-våg - - - User defined wave - Användardefinierad vågform - - - Smooth - Utjämna - - - Click here to smooth waveform. - - - - Normalize - Normalisera - - - Click here to normalize waveform. - - - + Use a sine-wave for current oscillator. + + Triangle wave + Triangelvåg + + + Use a triangle-wave for current oscillator. + + Saw wave + Sågtandsvåg + + + Use a saw-wave for current oscillator. + + Square wave + Fyrkantvåg + + + Use a square-wave for current oscillator. + + White noise wave + Vitt brus-våg + + + Use white-noise for current oscillator. + + User defined wave + Användardefinierad vågform + + + Use a user-defined waveform for current oscillator. - + Använd en användardefinierad vågform för aktuell oscillator. + + + + Smooth + Utjämna + + + + Click here to smooth waveform. + Klicka här för att jämna vågform. + + + + Normalize + Normalisera + + + + Click here to normalize waveform. + Klicka här för att normalisera vågformen. voiceObject + Voice %1 pulse width - + Röst %1 pulsbredd + Voice %1 attack - + Röst %1 attack + Voice %1 decay + Voice %1 sustain + Voice %1 release + Voice %1 coarse detuning + Voice %1 wave shape + Voice %1 sync + Voice %1 ring modulate + Voice %1 filtered - + Röst %1 filtrerad + Voice %1 test - + Röst %1 test waveShaperControlDialog + INPUT INGÅNG + Input gain: Ingångsförstärkning: + OUTPUT UTGÅNG + Output gain: Utgångsförstärkning: + Reset waveform Återställ vågform + Click here to reset the wavegraph back to default + Smooth waveform Mjuk vågform + Click here to apply smoothing to wavegraph + Increase graph amplitude by 1dB - + Öka grafamplituden med 1dB + Click here to increase wavegraph amplitude by 1dB - + Klicka här för att öka våggrafamplituden med 1dB + Decrease graph amplitude by 1dB - + Minska grafamplituden med 1dB + Click here to decrease wavegraph amplitude by 1dB + Clip input + Clip input signal to 0dB @@ -9942,10 +12731,12 @@ The LED in the lower right corner of the waveform editor determines whether the waveShaperControls + Input gain Ingångsförstärkning + Output gain Utgångsförstärkning diff --git a/data/locale/uk.ts b/data/locale/uk.ts index 43931a173..c088f401c 100644 --- a/data/locale/uk.ts +++ b/data/locale/uk.ts @@ -2,30 +2,62 @@ AboutDialog + About LMMS Про програму LMMS + + LMMS + LMMS + + + Version %1 (%2/%3, Qt %4, %5) Версія %1 (%2/%3, Qt %4, %5) + About Про програму + LMMS - easy music production for everyone LMMS - легке створення музики для всіх + + Copyright © %1 + Авторське право © %1 + + + + <html><head/><body><p><a href="https://lmms.io"><span style=" text-decoration: underline; color:#0000ff;">https://lmms.io</span></a></p></body></html> + <html><head/><body><p><a href="https://lmms.io"><span style=" text-decoration: underline; color:#0000ff;">https://lmms.io</span></a></p></body></html> + + + Authors Автори + + Involved + Учасники + + + + Contributors ordered by number of commits: + Розробники відсортовані за кількістю коммітов: + + + Translation Переклад + Current language not translated (or native English). If you're interested in translating LMMS in another language or want to improve existing translations, you're welcome to help us! Simply contact the maintainer! @@ -35,61 +67,50 @@ If you're interested in translating LMMS in another language or want to imp Якщо Ви зацікавлені в перекладі LMMS на іншу мову або хочете поліпшити існуючий переклад, ми будемо раді будь-якій допомогі! Просто зв'яжіться з розробниками! + License Ліцензія - - LMMS - LMMS - - - Involved - Учасники - - - Contributors ordered by number of commits: - Розробники відсортовані за кількістю коммітов: - - - Copyright © %1 - Авторське право © %1 - - - <html><head/><body><p><a href="https://lmms.io"><span style=" text-decoration: underline; color:#0000ff;">https://lmms.io</span></a></p></body></html> - - AmplifierControlDialog + VOL ГУЧН + Volume: Гучність: + PAN БАЛ + Panning: Баланс: + LEFT ЛІВЕ + Left gain: Ліве підсилення: + RIGHT ПРАВЕ + Right gain: Праве підсилення: @@ -97,18 +118,22 @@ If you're interested in translating LMMS in another language or want to imp AmplifierControls + Volume Гучність + Panning Баланс + Left gain Ліве підсилення + Right gain Праве підсилення @@ -116,10 +141,12 @@ If you're interested in translating LMMS in another language or want to imp AudioAlsaSetupWidget + DEVICE ПРИСТРІЙ + CHANNELS КАНАЛИ @@ -127,78 +154,98 @@ If you're interested in translating LMMS in another language or want to imp AudioFileProcessorView + Open other sample Відкрити інший запис + Click here, if you want to open another audio-file. A dialog will appear where you can select your file. Settings like looping-mode, start and end-points, amplify-value, and so on are not reset. So, it may not sound like the original sample. Натисніть тут, щоб відкрити інший звуковий файл. У новому вікні діалогу ви зможете вибрати потрібний файл. Такі налаштування, як режим повтору, точки початку/кінця, підсилення та інші не скинуться, тому звучання може відрізнятися від оригіналу. + Reverse sample Реверс запису + If you enable this button, the whole sample is reversed. This is useful for cool effects, e.g. a reversed crash. Якщо включити цю кнопку, весь запис піде у зворотний бік, це зручно для крутих ефектів, наприклад зворотного гуркоту. - Amplify: - Підсилення: - - - With this knob you can set the amplify ratio. When you set a value of 100% your sample isn't changed. Otherwise it will be amplified up or down (your actual sample-file isn't touched!) - Ця ручка задає коефіцієнт підсилення. При значенні 100% вихідний звук не змінюється, в іншому випадку - він буде ослаблений або підсилений. (Зверніть увагу, що вихідний запис при цьому залишиться недоторканим.) - - - Startpoint: - Початок: - - - Endpoint: - Кінець: - - - Continue sample playback across notes - Продовжити відтворення запису по нотах - - - Enabling this option makes the sample continue playing across different notes - if you change pitch, or the note length stops before the end of the sample, then the next note played will continue where it left off. To reset the playback to the start of the sample, insert a note at the bottom of the keyboard (< 20 Hz) - Включення цієї опції продовжить відтворення запису за різними нотами - якщо змінити прискорення або тривалість ноти зупиниться до кінця запису, то з наступної ноти запис продовжиться там, де зупинився, щоб скинути відтворення на початок запису, вставте ноту внизу у клавіш (<20 Гц) - - + Disable loop Відключити повторення + This button disables looping. The sample plays only once from start to end. Ця кнопка відключає повтор. Запис програється тільки один раз від початку до кінця. + + Enable loop Включити повторення + This button enables forwards-looping. The sample loops between the end point and the loop point. Ця кнопка включає передній повтор. Запис повторюється між кінцевою точкою і точкою повтору. + This button enables ping-pong-looping. The sample loops backwards and forwards between the end point and the loop point. Ця кнопка включає пінг-понг петлю. Запис повторюється назад і вперед між кінцевою точкою і точкою повтору. + + Continue sample playback across notes + Продовжити відтворення запису по нотах + + + + Enabling this option makes the sample continue playing across different notes - if you change pitch, or the note length stops before the end of the sample, then the next note played will continue where it left off. To reset the playback to the start of the sample, insert a note at the bottom of the keyboard (< 20 Hz) + Включення цієї опції продовжить відтворення запису за різними нотами - якщо змінити прискорення або тривалість ноти зупиниться до кінця запису, то з наступної ноти запис продовжиться там, де зупинився, щоб скинути відтворення на початок запису, вставте ноту внизу у клавіш (<20 Гц) + + + + Amplify: + Підсилення: + + + + With this knob you can set the amplify ratio. When you set a value of 100% your sample isn't changed. Otherwise it will be amplified up or down (your actual sample-file isn't touched!) + Ця ручка задає коефіцієнт підсилення. При значенні 100% вихідний звук не змінюється, в іншому випадку - він буде ослаблений або підсилений. (Зверніть увагу, що вихідний запис при цьому залишиться недоторканим.) + + + + Startpoint: + Початок: + + + With this knob you can set the point where AudioFileProcessor should begin playing your sample. Цим регулятором можна встановити мітку з якої АудіоФайлПроцессор повинен почати відтворення запису. + + Endpoint: + Кінець: + + + With this knob you can set the point where AudioFileProcessor should stop playing your sample. Цей регулятор встановлює мітку в якій АудіоФайлПроцессор повинен перестати програвати запис. + Loopback point: Точка повернення з повтору: + With this knob you can set the point where the loop starts. Цей регулятор ставить мітку початку повторення. @@ -206,6 +253,7 @@ If you're interested in translating LMMS in another language or want to imp AudioFileProcessorWaveView + Sample length: Довжина запису: @@ -213,26 +261,32 @@ If you're interested in translating LMMS in another language or want to imp AudioJack + JACK client restarted JACK-клієнт перезапущений + LMMS was kicked by JACK for some reason. Therefore the JACK backend of LMMS has been restarted. You will have to make manual connections again. LMMS не був підключений до JACK з якоїсь причини, тому LMMS підключення до JACK було перезапущено. Вам доведеться заново вручну створити з'єднання. + JACK server down JACK-сервер не доступний + The JACK server seems to have been shutdown and starting a new instance failed. Therefore LMMS is unable to proceed. You should save your project and restart JACK and LMMS. Можливо JACK-сервер був вимкнений і запуск нового процесу не вдався, тому LMMS не може продовжити роботу. Вам слід зберегти проект і перезапустити JACK і LMMS. + CLIENT-NAME ІМ'Я КЛІЄНТА + CHANNELS КАНАЛИ @@ -240,10 +294,12 @@ If you're interested in translating LMMS in another language or want to imp AudioOss::setupWidget + DEVICE ПРИСТРІЙ + CHANNELS КАНАЛИ @@ -251,10 +307,12 @@ If you're interested in translating LMMS in another language or want to imp AudioPortAudio::setupWidget + BACKEND УПРАВЛІННЯ + DEVICE ПРИСТРІЙ @@ -262,10 +320,12 @@ If you're interested in translating LMMS in another language or want to imp AudioPulseAudio::setupWidget + DEVICE ПРИСТРІЙ + CHANNELS КАНАЛИ @@ -273,6 +333,7 @@ If you're interested in translating LMMS in another language or want to imp AudioSdl::setupWidget + DEVICE ПРИСТРІЙ @@ -280,10 +341,12 @@ If you're interested in translating LMMS in another language or want to imp AudioSndio::setupWidget + DEVICE ПРИСТРІЙ + CHANNELS КАНАЛИ @@ -291,10 +354,12 @@ If you're interested in translating LMMS in another language or want to imp AudioSoundIo::setupWidget + BACKEND УПРАВЛІННЯ + DEVICE ПРИСТРІЙ @@ -302,61 +367,75 @@ If you're interested in translating LMMS in another language or want to imp AutomatableModel + &Reset (%1%2) &R Скинути (%1%2) + &Copy value (%1%2) &C Копіювати значення (%1%2) + &Paste value (%1%2) &P Вставити значення (%1%2) + Edit song-global automation Змінити глоабльную автоматизацію композиції - Connected to %1 - Приєднано до %1 - - - Connected to controller - Приєднано до контролера - - - Edit connection... - Налаштувати з'єднання... - - - Remove connection - Видалити з'єднання - - - Connect to controller... - З'єднати з контролером ... - - + Remove song-global automation Прибрати глобальну автоматизацію композиції + Remove all linked controls Прибрати все приєднане управління + + + Connected to %1 + Приєднано до %1 + + + + Connected to controller + Приєднано до контролера + + + + Edit connection... + Налаштувати з'єднання... + + + + Remove connection + Видалити з'єднання + + + + Connect to controller... + З'єднати з контролером ... + AutomationEditor + Please open an automation pattern with the context menu of a control! Відкрийте редатор автоматизації через контекстне меню регулятора! + Values copied Значення скопійовані + All selected values were copied to the clipboard. Всі вибрані значення скопійовані до буферу обміну. @@ -364,159 +443,194 @@ If you're interested in translating LMMS in another language or want to imp AutomationEditorWindow + Play/pause current pattern (Space) Гра/Пауза поточної мелодії (Пробіл) + Click here if you want to play the current pattern. This is useful while editing it. The pattern is automatically looped when the end is reached. Натисніть тут щоб програти поточну мелодію. Це може стати в нагоді при його редагуванні. Мелодія автоматично програватиме знову при досягненні кінця. + Stop playing of current pattern (Space) Зупинити програвання поточної мелодії (Пробіл) + Click here if you want to stop playing of the current pattern. Натисніть тут, якщо ви хочете зупинити відтворення поточної мелодії. + + Edit actions + Зміна + + + Draw mode (Shift+D) Режим малювання (Shift + D) + Erase mode (Shift+E) Режим стирання (Shift+E) + Flip vertically Перевернути вертикально + Flip horizontally Перевернути горизонтально + Click here and the pattern will be inverted.The points are flipped in the y direction. Натисніть тут і мелодія перевернеться. Точки перевертаються в Y напрямку. + Click here and the pattern will be reversed. The points are flipped in the x direction. Натисніть тут і мелодія перевернеться в напрямку X. + Click here and draw-mode will be activated. In this mode you can add and move single values. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. При натиснені цієї кнопки активується режим малювання нот, в ньому ви можете додавати/переміщати і змінювати тривалість одиночних нот. Це основний режим і використовується більшу частину часу. Для увімкнення цього режиму можна скористатися комбінацію клавіш Shift+D. + Click here and erase-mode will be activated. In this mode you can erase single values. You can also press 'Shift+E' on your keyboard to activate this mode. При натиснені цієї кнопки активується режим стирання. У цьому режимі ви можете видаляти ноти по одній. Для увімкнення цього режиму можна скористатися комбінацію клавіш Shift+E. - Discrete progression - Дискретна прогресія - - - Linear progression - Лінійна прогресія - - - Cubic Hermite progression - Кубічна Ермітова прогресія - - - Tension value for spline - Величина напруженості для сплайна - - - A higher tension value may make a smoother curve but overshoot some values. A low tension value will cause the slope of the curve to level off at each control point. - Більш висока напруженість може зробити криву більш м'якою, але перевантажить деякі величини. Низька напруженість зробить нахил кривої нижчою в кожній контрольній точці. - - - Click here to choose discrete progressions for this automation pattern. The value of the connected object will remain constant between control points and be set immediately to the new value when each control point is reached. - Вибір дискретної прогресії для цього шаблону автоматизації. Кількість приєднаних об'єктів залишатиметься постійним між керуючими точками і буде встановлена на нове значення відразу після досягнення кожної керуючої точки. - - - Click here to choose linear progressions for this automation pattern. The value of the connected object will change at a steady rate over time between control points to reach the correct value at each control point without a sudden change. - Вибір лінійної прогресії для цього шаблону автоматизації. Кількість приєднаних об'єктів буде змінюватися з постійною швидкістю в часі між керуючими точками для досягнення точного значення в кожній керуючій точці без раптових змін. - - - Click here to choose cubic hermite progressions for this automation pattern. The value of the connected object will change in a smooth curve and ease in to the peaks and valleys. - Кубічна Ермітова прогресія для цього шаблону автоматизації. Кількість приєднаних об'єктів зміниться по згладженій кривій і пом'якшиться на піках і спадах. - - - Cut selected values (%1+X) - Вирізати вибрані ноти (%1+X) - - - Copy selected values (%1+C) - Копіювати вибрані ноти до буферу (%1+C) - - - Paste values from clipboard (%1+V) - Вставити значення з буферу (%1+V) - - - Click here and selected values will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. - При натиснені цієї кнопки виділені ноти будуть вирізані до буферу. Пізніше ви можете вставити їх в будь-яке місце будь-якого шаблону за допомогою кнопки "Вставити". - - - Click here and selected values will be copied into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. - При натиснені цієї кнопки виділені ноти будуть скопійовано до буферу. Пізніше ви зможете вставити їх в будь-яке місце будь-якого шаблону за допомогою кнопки "Вставити". - - - Click here and the values from the clipboard will be pasted at the first visible measure. - При натиснені цієї кнопки ноти з буферу будуть вставлені в перший видимий такт. - - - Tension: - Напруженість: - - - Automation Editor - no pattern - Редактор автоматизації - немає шаблону - - - Automation Editor - %1 - Редактор автоматизації - %1 - - - Edit actions - Зміна - - + Interpolation controls Управління інтерполяцією - Timeline controls - Управління хронологією + + Discrete progression + Дискретна прогресія + + Linear progression + Лінійна прогресія + + + + Cubic Hermite progression + Кубічна Ермітова прогресія + + + + Tension value for spline + Величина напруженості для сплайна + + + + A higher tension value may make a smoother curve but overshoot some values. A low tension value will cause the slope of the curve to level off at each control point. + Більш висока напруженість може зробити криву більш м'якою, але перевантажить деякі величини. Низька напруженість зробить нахил кривої нижчою в кожній контрольній точці. + + + + Click here to choose discrete progressions for this automation pattern. The value of the connected object will remain constant between control points and be set immediately to the new value when each control point is reached. + Вибір дискретної прогресії для цього шаблону автоматизації. Кількість приєднаних об'єктів залишатиметься постійним між керуючими точками і буде встановлена на нове значення відразу після досягнення кожної керуючої точки. + + + + Click here to choose linear progressions for this automation pattern. The value of the connected object will change at a steady rate over time between control points to reach the correct value at each control point without a sudden change. + Вибір лінійної прогресії для цього шаблону автоматизації. Кількість приєднаних об'єктів буде змінюватися з постійною швидкістю в часі між керуючими точками для досягнення точного значення в кожній керуючій точці без раптових змін. + + + + Click here to choose cubic hermite progressions for this automation pattern. The value of the connected object will change in a smooth curve and ease in to the peaks and valleys. + Кубічна Ермітова прогресія для цього шаблону автоматизації. Кількість приєднаних об'єктів зміниться по згладженій кривій і пом'якшиться на піках і спадах. + + + + Tension: + Напруженість: + + + + Cut selected values (%1+X) + Вирізати вибрані ноти (%1+X) + + + + Copy selected values (%1+C) + Копіювати вибрані ноти до буферу (%1+C) + + + + Paste values from clipboard (%1+V) + Вставити значення з буферу (%1+V) + + + + Click here and selected values will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. + При натиснені цієї кнопки виділені ноти будуть вирізані до буферу. Пізніше ви можете вставити їх в будь-яке місце будь-якого шаблону за допомогою кнопки "Вставити". + + + + Click here and selected values will be copied into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. + При натиснені цієї кнопки виділені ноти будуть скопійовано до буферу. Пізніше ви зможете вставити їх в будь-яке місце будь-якого шаблону за допомогою кнопки "Вставити". + + + + Click here and the values from the clipboard will be pasted at the first visible measure. + При натиснені цієї кнопки ноти з буферу будуть вставлені в перший видимий такт. + + + Zoom controls Управління масштабом + Quantization controls Управління квантуванням + + Quantization + Квантування + + + + Quantization. Sets the smallest step size for the Automation Point. By default this also sets the length, clearing out other points in the range. Press <Ctrl> to override this behaviour. + Квантування. Встановлює найменший розмір кроку для точки автоматизації. За замовчуванням це також задає довжину, очищаючи інші точки діапазону. Натисніть <Ctrl>, щоб змінити цю поведінку. + + + + + Automation Editor - no pattern + Редактор автоматизації - немає шаблону + + + + + Automation Editor - %1 + Редактор автоматизації - %1 + + + Model is already connected to this pattern. Модель вже підключена до цього шаблону. - - Quantization - - - - Quantization. Sets the smallest step size for the Automation Point. By default this also sets the length, clearing out other points in the range. Press <Ctrl> to override this behaviour. - - AutomationPattern + Drag a control while pressing <%1> Тягніть контроль утримуючи <%1> @@ -524,42 +638,57 @@ If you're interested in translating LMMS in another language or want to imp AutomationPatternView + + double-click to open this pattern in automation editor + Двічі клацніть мишею щоб налаштувати автоматизацію для цього шаблону + + + Open in Automation editor Відкрити в редакторі автоматизації + Clear Очистити + Reset name Скинути назву + Change name Перейменувати - %1 Connections - З'єднання %1 - - - Disconnect "%1" - Від'єднати «%1» - - + Set/clear record Встановити/очистити запис + Flip Vertically (Visible) Перевернути вертикально (Видиме) + Flip Horizontally (Visible) Перевернути горизонтально (Видиме) + + %1 Connections + З'єднання %1 + + + + Disconnect "%1" + Від'єднати «%1» + + + Model is already connected to this pattern. Модель вже підключена до цього шаблону. @@ -567,6 +696,7 @@ If you're interested in translating LMMS in another language or want to imp AutomationTrack + Automation track Доріжка автоматизації @@ -574,77 +704,95 @@ If you're interested in translating LMMS in another language or want to imp BBEditor + Beat+Bassline Editor Ритм Бас Редактор + Play/pause current beat/bassline (Space) Грати/пауза поточної лінії ритму/басу (Пробіл) + Stop playback of current beat/bassline (Space) Зупинити відтворення поточної лінії ритм-басу (Пробіл) + Click here to play the current beat/bassline. The beat/bassline is automatically looped when its end is reached. Натисніть щоб програти поточну лінію ритм-басу. Вона буде повторена при досягненні кінця. + Click here to stop playing of current beat/bassline. Зупинити відтворення (Пробіл). - Add beat/bassline - Додати ритм/бас - - - Add automation-track - Додати доріжку автоматизації - - - Remove steps - Видалити такти - - - Add steps - Додати такти - - + Beat selector Вибір ударних + Track and step actions Дії для доріжки чи її частини - Clone Steps - Клонувати такти + + Add beat/bassline + Додати ритм/бас + Add sample-track Додати доріжку запису + + + Add automation-track + Додати доріжку автоматизації + + + + Remove steps + Видалити такти + + + + Add steps + Додати такти + + + + Clone Steps + Клонувати такти + BBTCOView + Open in Beat+Bassline-Editor Відкрити в редакторі ритму і басу + Reset name Скинути назву + Change name Перейменувати + Change color Змінити колір + Reset color to default Відновити колір за замовчуванням @@ -652,10 +800,12 @@ If you're interested in translating LMMS in another language or want to imp BBTrack + Beat/Bassline %1 Ритм/Бас лінія %1 + Clone of %1 Копія %1 @@ -663,26 +813,32 @@ If you're interested in translating LMMS in another language or want to imp BassBoosterControlDialog + FREQ ЧАСТ + Frequency: Частота: + GAIN ПІДС + Gain: Підсилення: + RATIO ВІДН + Ratio: Відношення: @@ -690,14 +846,17 @@ If you're interested in translating LMMS in another language or want to imp BassBoosterControls + Frequency Частота + Gain Підсилення + Ratio Відношення @@ -705,89 +864,111 @@ If you're interested in translating LMMS in another language or want to imp BitcrushControlDialog + IN ВХД + OUT ВИХ + + GAIN ПІДС + Input Gain: Вхідне підсилення: + + NOISE + ШУМ + + + Input Noise: Вхідний шум: + Output Gain: Вихідне підсилення: + CLIP ЗРІЗ + Output Clip: Вихідне відсічення: + Rate Enabled Частоту вибірки увімкнено + Enable samplerate-crushing Включити дроблення частоти дискретизації + Depth Enabled Глибина включена + Enable bitdepth-crushing Включити ​​дроблення глибини кольору - Sample rate: - Частота дискретизації: - - - Stereo difference: - Стерео різниця: - - - Levels: - Рівні: - - - NOISE - - - + FREQ ЧАСТ - STEREO - + + Sample rate: + Частота дискретизації: + + STEREO + СТЕРЕО + + + + Stereo difference: + Стерео різниця: + + + QUANT - + КВАНТ + + + + Levels: + Рівні: CaptionMenu + &Help &H Довідка + Help (not available) Допомога (не доступно) @@ -795,10 +976,12 @@ If you're interested in translating LMMS in another language or want to imp CarlaInstrumentView + Show GUI Показати інтерфейс + Click here to show or hide the graphical user interface (GUI) of Carla. Натисніть сюди щоб сховати чи показати графічний інтерфейс Carla. @@ -806,6 +989,7 @@ If you're interested in translating LMMS in another language or want to imp Controller + Controller %1 Контролер %1 @@ -813,58 +997,73 @@ If you're interested in translating LMMS in another language or want to imp ControllerConnectionDialog + Connection Settings Параметры соединения + MIDI CONTROLLER MIDI-КОНТРОЛЕР + Input channel Канал введення + CHANNEL КАНАЛ + Input controller Контролер введення + CONTROLLER КОНТРОЛЕР + + Auto Detect Автовизначення + MIDI-devices to receive MIDI-events from Пристрої MiDi для прийому подій + USER CONTROLLER КОРИСТ. КОНТРОЛЕР + MAPPING FUNCTION ПЕРЕВИЗНАЧЕННЯ + OK ОК + Cancel Відміна + LMMS ЛММС + Cycle Detected. Виявлено цикл. @@ -872,18 +1071,22 @@ If you're interested in translating LMMS in another language or want to imp ControllerRackView + Controller Rack Стійка контролерів + Add Додати + Confirm Delete Підтвердити видалення + Confirm delete? There are existing connection(s) associated with this controller. There is no way to undo. Чи підтверджуєте видалення? Є можливі зв'язки з цим контролером, потім їх не можна буде повернути.. @@ -891,93 +1094,115 @@ If you're interested in translating LMMS in another language or want to imp ControllerView + Controls Управління + Controllers are able to automate the value of a knob, slider, and other controls. Контролери можуть автоматизувати зміни значень регуляторів, повзунків та іншого управління. + Rename controller Перейменувати контролер + Enter the new name for this controller Введіть нову назву контролера + + LFO + LFO + + + &Remove this controller &R Видалити цей контролер + Re&name this controller &N Перейменувати цей контролер - - LFO - LFO - CrossoverEQControlDialog + Band 1/2 Crossover: Смуга 1/2 кросовер: + Band 2/3 Crossover: Смуга 2/3 кросовер: + Band 3/4 Crossover: Смуга 3/4 кросовер: + Band 1 Gain: Смуга 1 підсилення: + Band 2 Gain: Смуга 2 підсилення: + Band 3 Gain: Смуга 3 підсилення: + Band 4 Gain: Смуга 4 підсилення: + Band 1 Mute Смуга 1 відключена + Mute Band 1 Відключити смугу 1 + Band 2 Mute Смуга 2 відключена + Mute Band 2 Відключити смугу 2 + Band 3 Mute Смуга 3 відключена + Mute Band 3 Відключити смугу 3 + Band 4 Mute Смуга 4 відключена + Mute Band 4 Відключити смугу 4 @@ -985,22 +1210,27 @@ If you're interested in translating LMMS in another language or want to imp DelayControls + Delay Samples Затримка семплів + Feedback Повернення + Lfo Frequency Частота LFO + Lfo Amount Величина LFO + Output gain Вихідне підсилення @@ -1008,228 +1238,311 @@ If you're interested in translating LMMS in another language or want to imp DelayControlsDialog - Lfo Amt - Вел LFO + + DELAY + ЗАТРИМ + Delay Time Час затримки + + FDBK + FDBK + + + Feedback Amount Величина повернення + + RATE + ЧАСТ + + + Lfo LFO + + AMNT + ГЛИБ + + + + Lfo Amt + Вел LFO + + + Out Gain Вих підсилення + Gain Підсилення - - DELAY - - - - FDBK - - - - RATE - - - - AMNT - ГЛИБ - DualFilterControlDialog - Filter 1 enabled - Фільтр 1 включено - - - Filter 2 enabled - Фільтр 2 включено - - - Click to enable/disable Filter 1 - Натиснути для включення/виключення Фільтру 1 - - - Click to enable/disable Filter 2 - Натиснути для включення/виключення Фільтру 2 - - + + FREQ ЧАСТ + + Cutoff frequency Зріз частоти + + RESO РЕЗО + + Resonance Резонанс + + GAIN ПІДС + + Gain Підсилення + MIX МІКС + Mix Мікс + + + Filter 1 enabled + Фільтр 1 включено + + + + Filter 2 enabled + Фільтр 2 включено + + + + Click to enable/disable Filter 1 + Натиснути для включення/виключення Фільтру 1 + + + + Click to enable/disable Filter 2 + Натиснути для включення/виключення Фільтру 2 + DualFilterControls + Filter 1 enabled Фільтр 1 включено + Filter 1 type Тип фільтру + Cutoff 1 frequency Зріз 1 частоти + Q/Resonance 1 Кіл./Резонансу 1 + Gain 1 Підсилення 1 + Mix Мікс + Filter 2 enabled Фільтр 2 включено + Filter 2 type Тип фільтру 2 + Cutoff 2 frequency Зріз 2 частоти + Q/Resonance 2 Кіл./Резонансу 2 + Gain 2 Підсилення 2 + + LowPass Низ.ЧФ + + HiPass Вис.ЧФ + + BandPass csg Серед.ЧФ csg + + BandPass czpg Серед.ЧФ czpg + + Notch Смуго-загороджуючий + + Allpass Всі проходять + + Moog Муг + + 2x LowPass 2х Низ.ЧФ + + RC LowPass 12dB RC Низ.ЧФ 12дБ + + RC BandPass 12dB RC Серед.ЧФ 12 дБ + + RC HighPass 12dB RC Вис.ЧФ 12дБ + + RC LowPass 24dB RC Низ.ЧФ 24дБ + + RC BandPass 24dB RC Серед.ЧФ 24дБ + + RC HighPass 24dB RC Вис.ЧФ 24дБ + + Vocal Formant Filter Фільтр Вокальної форманти + + 2x Moog 2x Муг + + SV LowPass SV Низ.ЧФ + + SV BandPass SV Серед.ЧФ + + SV HighPass SV Вис.ЧФ + + SV Notch SV Смуго-заг + + Fast Formant Швидка форманта + + Tripole Тріполі @@ -1237,41 +1550,50 @@ If you're interested in translating LMMS in another language or want to imp Editor + + Transport controls + Управління засобами сполучення + + + Play (Space) Грати (Пробіл) + Stop (Space) Зупинити (Пробіл) + Record Запис + Record while playing Запис під час програвання - - Transport controls - Управління засобами сполучення - Effect + Effect enabled Ефект включений + Wet/Dry mix Насиченість + Gate Шлюз + Decay Згасання @@ -1279,6 +1601,7 @@ If you're interested in translating LMMS in another language or want to imp EffectChain + Effects enabled Ефекти включені @@ -1286,10 +1609,12 @@ If you're interested in translating LMMS in another language or want to imp EffectRackView + EFFECTS CHAIN МЕРЕЖА ЕФЕКТІВ + Add effect Додати ефект @@ -1297,22 +1622,28 @@ If you're interested in translating LMMS in another language or want to imp EffectSelectDialog + Add effect Додати ефект + + Name І'мя + Type Тип + Description Опис + Author Автор @@ -1320,54 +1651,67 @@ If you're interested in translating LMMS in another language or want to imp EffectView + Toggles the effect on or off. Увімк/Вимк ефект. + On/Off Увімк/Вимк + W/D НАСИЧ + Wet Level: Рівень насиченості: + The Wet/Dry knob sets the ratio between the input signal and the effect signal that forms the output. Регулятор насиченості визначає частку обробленого сигналу, яка буде на виході. + DECAY - ЗГАСАННЯ + + Time: Час: + The Decay knob controls how many buffers of silence must pass before the plugin stops processing. Smaller values will reduce the CPU overhead but run the risk of clipping the tail on delay and reverb effects. Decay (затихання) управляє кількістю буферів тиші, які повинні пройти до кінця роботи плагіна. Менші величини знижують перевантаження процесора, але виникає ризик появи потріскування або підрізання в хвості на перетримці (delay) або відлуння (reverb) ефектах. + GATE ШЛЮЗ + Gate: Шлюз: + The Gate knob controls the signal level that is considered to be 'silence' while deciding when to stop processing signals. GATE (Шлюз) визначає рівень сигналу, який буде вважатися "тишею" при визначенні зупинки оброблення сигналів. + Controls Управління + Effect plugins function as a chained series of effects where the signal will be processed from top to bottom. The On/Off switch allows you to bypass a given plugin at any point in time. @@ -1397,14 +1741,17 @@ Right clicking will bring up a context menu where you can change the order in wh Контекстне меню, яке викликається клацанням правою кнопкою миші, дозволяє змінювати порядок проходження фільтрів або видаляти їх разом з іншими. + Move &up &u Перемістити вище + Move &down &d Перемістити нижче + &Remove this plugin &R Видалити цей плагін @@ -1412,58 +1759,72 @@ Right clicking will bring up a context menu where you can change the order in wh EnvelopeAndLfoParameters + Predelay Затримка + Attack Вступ + Hold Утримання + Decay Згасання + Sustain Витримка + Release Зменшення + Modulation Модуляція + LFO Predelay Затримка LFO + LFO Attack Вступ LFO + LFO speed Швидкість LFO + LFO Modulation Модуляція LFO + LFO Wave Shape Форма сигналу LFO + Freq x 100 ЧАСТ x 100 + Modulate Env-Amount Модулювати обвідну @@ -1471,349 +1832,439 @@ Right clicking will bring up a context menu where you can change the order in wh EnvelopeAndLfoView + + DEL DEL + Predelay: Предзатримка: + Use this knob for setting predelay of the current envelope. The bigger this value the longer the time before start of actual envelope. Ця ручка визначає затримку обвідної. Чим більша ця величина, тим довший час до старту поточної обвідної. + + ATT ATT + Attack: Вступ: + Use this knob for setting attack-time of the current envelope. The bigger this value the longer the envelope needs to increase to attack-level. Choose a small value for instruments like pianos and a big value for strings. Ця ручка встановлює час зростання для поточної обвідної. Чим більше значення, тим довше характеристика (н-д, гучність) зростає до максимуму. Для інструменов нашталт піаніно характерний малий час наростання, а для струнних - великий. + HOLD HOLD + Hold: Утримання: + Use this knob for setting hold-time of the current envelope. The bigger this value the longer the envelope holds attack-level before it begins to decrease to sustain-level. Ця ручка встановлює тривалість обвідної. Чим більше значення, тим довше обвідна тримається на найвищому рівні. + DEC DEC + Decay: Згасання: + Use this knob for setting decay-time of the current envelope. The bigger this value the longer the envelope needs to decrease from attack-level to sustain-level. Choose a small value for instruments like pianos. Ця ручка встановлює час згасання для поточної обвідної. Чим більше значення, тим довше обвідна повинна зменшуватися від вступу до рівня витримки. Для інструментів накшталт піаніно слід вибирати невеликі значення. + SUST SUST + Sustain: Витримка: + Use this knob for setting sustain-level of the current envelope. The bigger this value the higher the level on which the envelope stays before going down to zero. Ця ручка встановлює рівень витримки. Чим більша ця величина, тим вище рівень на якому залишається обвідна, перш ніж опуститися до нуля. + REL REL + Release: Зменшення: + Use this knob for setting release-time of the current envelope. The bigger this value the longer the envelope needs to decrease from sustain-level to zero. Choose a big value for soft instruments like strings. Ця ручка встановлює час відпускання для поточної обвідної. Чим більше значення, тим довша характеристика (н-д, гучність) зменшується від рівня витримки до нуля. Для струнних інструментів слід вибирати великі значення. + + AMT AMT + + Modulation amount: Глибина модуляції: + Use this knob for setting modulation amount of the current envelope. The bigger this value the more the according size (e.g. volume or cutoff-frequency) will be influenced by this envelope. Ця ручка встановлює глибину модуляції для поточної обвідної. Чим більше значення, тим більшою мірою обрана характеристика (н-д, гучність або частота зрізу) буде залежати від цієї обвідної. + LFO predelay: Предзатримка LFO: + Use this knob for setting predelay-time of the current LFO. The bigger this value the the time until the LFO starts to oscillate. Ця ручка визначає затримку перед запуском LFO (LFO - низькочастотний осциллятор (генератор)). Чим більша величина, тим більше часу до того як LFO почне працювати. + LFO- attack: Вступ LFO: + Use this knob for setting attack-time of the current LFO. The bigger this value the longer the LFO needs to increase its amplitude to maximum. Використовуйте цю ручку для встановлення часу вступу цього LFO. Чим більше значення, тим довше LFO потребує збільшення своєї амплітуди до максимуму. + SPD SPD + LFO speed: Швидкість LFO: + Use this knob for setting speed of the current LFO. The bigger this value the faster the LFO oscillates and the faster will be your effect. Ця ручка встановлює швидкість поточного LFO. Чим більше значення, тим швидше LFO коливається і швидше виробляється ефект. + Use this knob for setting modulation amount of the current LFO. The bigger this value the more the selected size (e.g. volume or cutoff-frequency) will be influenced by this LFO. Ця ручка встановлює глибину модуляції для поточного LFO. Чим більше значення, тим більшою мірою обрана характеристика (н-д, гучність або частота зрізу) залежатиме від цього LFO. + Click here for a sine-wave. - Генерувати гармонійний (синусоїдальний) сигнал. + Синусоїда. + Click here for a triangle-wave. Згенерувати трикутний сигнал. + Click here for a saw-wave for current. Згенерувати зигзагоподібний сигнал. + Click here for a square-wave. Згенерувати квадратний сигнал. + Click here for a user-defined wave. Afterwards, drag an according sample-file onto the LFO graph. Задати свою форму сигналу. Згодом, перетягнути відповідний файл із записом в граф LFO. + + Click here for random wave. + Натисніть сюди для випадкової хвилі. + + + FREQ x 100 ЧАСТОТА x 100 + Click here if the frequency of this LFO should be multiplied by 100. Натисніть, щоб помножити частоту цього LFO на 100. + multiply LFO-frequency by 100 Помножити частоту LFO на 100 + MODULATE ENV-AMOUNT МОДЕЛЮВ ОБВІДНУ + Click here to make the envelope-amount controlled by this LFO. Натисніть сюди, щоб глибина модуляції обвідної задавалася цим LFO. + control envelope-amount by this LFO Дозволити цьому LFO задавати значення обвідної + ms/LFO: мс/LFO: + Hint Підказка + Drag a sample from somewhere and drop it in this window. Перетягніть в це вікно який-небудь запис. - - Click here for random wave. - Натисніть сюди для випадкової хвилі. - EqControls + Input gain Вхідне підсилення + Output gain Вихідне підсилення + Low shelf gain Мала ступінь підсилення + Peak 1 gain Пік 1 підсилення + Peak 2 gain Пік 2 підсилення + Peak 3 gain Пік 3 підсилення + Peak 4 gain Пік 4 підсилення + High Shelf gain Висока ступінь підсилення + HP res ВЧ резон + Low Shelf res Мала ступінь резон + Peak 1 BW Пік 1 BW + Peak 2 BW Пік 2 BW + Peak 3 BW Пік 3 BW + Peak 4 BW Пік 4 BW + High Shelf res Висока ступінь резон + LP res НЧ резон + HP freq НЧ част + Low Shelf freq Низька ступінь част + Peak 1 freq Пік 1 част + Peak 2 freq Пік 2 част + Peak 3 freq Пік 3 част + Peak 4 freq Пік 4 част + High shelf freq Висока ступінь част + LP freq НЧ част + HP active ВЧ активна + Low shelf active Мала ступінь активна + Peak 1 active Пік 1 активний + Peak 2 active Пік 2 активний + Peak 3 active Пік 3 активний + Peak 4 active Пік 4 активний + High shelf active Висока ступінь активна + LP active НЧ активна + LP 12 НЧ 12 + LP 24 НЧ 24 + LP 48 НЧ 48 + HP 12 ВЧ 12 + HP 24 ВЧ 24 + HP 48 ВЧ 48 + low pass type Тип низької частоти + high pass type Тип високої частоти + Analyse IN Аналізувати ВХІД + Analyse OUT Аналізувати ВИХІД @@ -1821,85 +2272,108 @@ Right clicking will bring up a context menu where you can change the order in wh EqControlsDialog + HP ВЧ + Low Shelf Мала ступінь + Peak 1 Пік 1 + Peak 2 Пік 2 + Peak 3 Пік 3 + Peak 4 Пік 4 + High Shelf Висока ступінь + LP НЧ + In Gain Вхід підсилення + + + Gain Підсилення + Out Gain Вих підсилення + Bandwidth: Ширина смуги: + + Octave + Октава + + + Resonance : Резонанс: + Frequency: Частота: + lp grp нч grp + hp grp вч grp - - Octave - Октава - EqHandle + Reso: Резон: + BW: ШС: + + Freq: Част: @@ -1907,190 +2381,237 @@ Right clicking will bring up a context menu where you can change the order in wh ExportProjectDialog + Export project Експорт проекту + Output Вивід + File format: Формат файла: + Samplerate: Частота дискретизації: + 44100 Hz 44.1 КГц + 48000 Hz 48 КГц + 88200 Hz 88.2 КГц + 96000 Hz 96 КГц + 192000 Hz 192 КГц - Bitrate: - Бітрейт: - - - 64 KBit/s - 64 КБіт/с - - - 128 KBit/s - 128 КБіт/с - - - 160 KBit/s - 160 КБіт/с - - - 192 KBit/s - 192 КБіт/с - - - 256 KBit/s - 256 КБіт/с - - - 320 KBit/s - 320 КБіт/с - - + Depth: Глибина: + 16 Bit Integer 16 Біт ціле + + 24 Bit Integer + 24 Біт ціле + + + 32 Bit Float 32 Біт плаваюча + + Stereo mode: + Стерео режим: + + + + Stereo + Стерео + + + + Joint Stereo + Об'єднане стерео + + + + Mono + Моно + + + + Bitrate: + Бітрейт: + + + + 64 KBit/s + 64 КБіт/с + + + + 128 KBit/s + 128 КБіт/с + + + + 160 KBit/s + 160 КБіт/с + + + + 192 KBit/s + 192 КБіт/с + + + + 256 KBit/s + 256 КБіт/с + + + + 320 KBit/s + 320 КБіт/с + + + + Use variable bitrate + Використовувати змінний бітрейт + + + Quality settings Налаштування якості + Interpolation: Інтерполяція: + Zero Order Hold Нульова затримка + Sinc Fastest Синхр. Швидка + Sinc Medium (recommended) Синхр. Середня (рекомендовано) + Sinc Best (very slow!) Синхр. краща (дуже повільно!) + Oversampling (use with care!): Передискретизація (використовувати обережно!): + 1x (None) 1х (Ні) + 2x + 4x + 8x - Start - Почати - - - Cancel - Відміна - - + Export as loop (remove end silence) Експортувати як петлю (прибрати тишу в кінці) + Export between loop markers Експорт між маркерами циклу + + Start + Почати + + + + Cancel + Відміна + + + Could not open file Не можу відкрити файл + + Could not open file %1 for writing. +Please make sure you have write permission to the file and the directory containing the file and try again! + Не вдалось відкрити файл %1 для запису. +Перевірте, чи маєте ви права на запис файлу і каталог що його містить і спробуйте знову! + + + Export project to %1 Експорт проекту в %1 + Error Помилка + Error while determining file-encoder device. Please try to choose a different output format. Помилка при визначенні кодека файлу. Спробуйте вибрати інший формат виводу. + Rendering: %1% Обробка: %1% - - Could not open file %1 for writing. -Please make sure you have write permission to the file and the directory containing the file and try again! - - - - 24 Bit Integer - - - - Use variable bitrate - - - - Stereo mode: - - - - Stereo - - - - Joint Stereo - - - - Mono - - Compression level: @@ -2154,6 +2675,8 @@ Please make sure you have write permission to the file and the directory contain Fader + + Please enter a new value between %1 and %2: Введіть нове значення від %1 до %2: @@ -2161,6 +2684,7 @@ Please make sure you have write permission to the file and the directory contain FileBrowser + Browser Оглядач файлів @@ -2176,65 +2700,80 @@ Please make sure you have write permission to the file and the directory contain FileBrowserTreeWidget + Send to active instrument-track З'єднати з активним інструментом-доріжкою - Open in new instrument-track/B+B Editor - Відкрити в новій інструментальній доріжці/Біт + Бас редакторі - - - Loading sample - Завантаження запису - - - Please wait, loading sample for preview... - Будь-ласка почекайте, запис завантажується для перегляду ... - - - --- Factory files --- - --- Заводські файли --- - - + Open in new instrument-track/Song Editor Відкрити в новій інструментальній доріжці/Музичному редакторі + + Open in new instrument-track/B+B Editor + Відкрити в новій інструментальній доріжці/Біт + Бас редакторі + + + + Loading sample + Завантаження запису + + + + Please wait, loading sample for preview... + Будь-ласка почекайте, запис завантажується для перегляду ... + + + Error Помилка + does not appear to be a valid не являється дійсним + file файл + + + --- Factory files --- + --- Заводські файли --- + FlangerControls + Delay Samples Затримка семплів + Lfo Frequency Частота LFO + Seconds Секунд + Regen Перегенерувати + Noise Шум + Invert Інвертувати @@ -2242,57 +2781,70 @@ Please make sure you have write permission to the file and the directory contain FlangerControlsDialog + + DELAY + ЗАТРИМ + + + Delay Time: Час затримки: - Feedback Amount: - Величина повернення: - - - White Noise Amount: - Об'єм білого шуму: - - - DELAY - - - + RATE - + ЧАСТ + + Period: + Період: + + + AMNT ГЛИБ + Amount: - + Величина: + FDBK - + FDBK + + Feedback Amount: + Величина повернення: + + + NOISE - + ШУМ + + White Noise Amount: + Об'єм білого шуму: + + + Invert Інвертувати - - Period: - - FxLine + Channel send amount Величина відправки каналу + The FX channel receives input from one or more instrument tracks. It in turn can be routed to multiple other FX channels. LMMS automatically takes care of preventing infinite loops for you and doesn't allow making a connection that would result in an infinite loop. @@ -2306,22 +2858,27 @@ You can remove and move FX channels in the context menu, which is accessed by ri Можна прибирати і рухати канали ефектів через контекстне меню, якщо натиснути правою кнопкою миші по каналу ефектів. + Move &left Рухати вліво &L + Move &right Рухати вправо &R + Rename &channel Перейменувати канал &C + R&emove channel Видалити канал &e + Remove &unused channels Видалити канали які &не використовуються @@ -2329,22 +2886,29 @@ You can remove and move FX channels in the context menu, which is accessed by ri FxMixer + Master Головний + + + FX %1 Ефект %1 + Volume Гучність + Mute Тиша + Solo Соло @@ -2352,26 +2916,32 @@ You can remove and move FX channels in the context menu, which is accessed by ri FxMixerView + FX-Mixer Мікшер Ефектів + FX Fader %1 Повзунок Ефекту %1 + Mute Тиша + Mute this FX channel Тиша на цьому каналі Ефекту + Solo Соло + Solo FX channel Соло каналу ЕФ @@ -2379,6 +2949,8 @@ You can remove and move FX channels in the context menu, which is accessed by ri FxRoute + + Amount to send from channel %1 to channel %2 Величина відправки з каналу %1 на канал %2 @@ -2386,14 +2958,17 @@ You can remove and move FX channels in the context menu, which is accessed by ri GigInstrument + Bank Банк + Patch Патч + Gain Підсилення @@ -2401,46 +2976,58 @@ You can remove and move FX channels in the context menu, which is accessed by ri GigInstrumentView + Open other GIG file Відкрити інший GIG файл + Click here to open another GIG file Натисніть, щоб відкрити інший GIG файл + Choose the patch Вибрати патч + Click here to change which patch of the GIG file to use Натисніть для зміни використовуваного патчу GIG файлу + + Change which instrument of the GIG file is being played Змінити інструмент, який відтворює GIG файл + Which GIG file is currently being used Який GIG файл зараз використовується + Which patch of the GIG file is currently being used Який патч GIG файлу зараз використовується + Gain Підсилення + Factor to multiply samples by Фактор множення семплів + Open GIG file Відкрити GIG файл + GIG Files (*.gig) GIG Файли (*.gig) @@ -2448,42 +3035,52 @@ You can remove and move FX channels in the context menu, which is accessed by ri GuiApplication + Working directory Робочий каталог LMMS + The LMMS working directory %1 does not exist. Create it now? You can change the directory later via Edit -> Settings. Робочий каталог LMMS (%1) не існує. Створити його? Пізніше ви зможете змінити його через Правку -> Параметри. + Preparing UI Підготовка користувацького інтерфейсу + Preparing song editor Підготовка музичного редактора + Preparing mixer Підготовка міксера + Preparing controller rack Підготовка стійки контролерів + Preparing project notes Підготовка заміток проекту + Preparing beat/bassline editor Підготовка ритм/бас редактора + Preparing piano roll Підготовка нотного редактора + Preparing automation editor Підготовка редактора автоматизації @@ -2491,650 +3088,814 @@ You can remove and move FX channels in the context menu, which is accessed by ri InstrumentFunctionArpeggio + Arpeggio Арпеджіо + Arpeggio type Тип арпеджіо + Arpeggio range Діапазон арпеджіо + + Cycle steps + Зациклити такти + + + + Skip rate + Частота пропуску + + + + Miss rate + Частота пропуску + + + Arpeggio time Період арпеджіо + Arpeggio gate Шлюз арпеджіо + Arpeggio direction Напрямок арпеджіо + Arpeggio mode Режим арпеджіо + Up Вгору + Down Вниз + Up and down Вгору та вниз - Random - Випадково - - - Free - Вільно - - - Sort - Сортувати - - - Sync - Синхронізувати - - + Down and up Вниз та вгору - Skip rate - + + Random + Випадково - Miss rate - + + Free + Вільно - Cycle steps - + + Sort + Сортувати + + + + Sync + Синхронізувати InstrumentFunctionArpeggioView + ARPEGGIO ARPEGGIO + An arpeggio is a method playing (especially plucked) instruments, which makes the music much livelier. The strings of such instruments (e.g. harps) are plucked like chords. The only difference is that this is done in a sequential order, so the notes are not played at the same time. Typical arpeggios are major or minor triads, but there are a lot of other possible chords, you can select. Арпеджіо - різновид виконання акордів на фортепіано і струнних інструментах, який оживляє звучання. Струни таких інструментів граються перебором по акордах, як на арфі, коли звуки акорду слідують один за іншим. Типові арпеджіо - мажорні та мінорні тріади, серед яких можна вибрати й інші. + RANGE RANGE + Arpeggio range: Діапазон арпеджіо: + octave(s) Октав(а/и) + Use this knob for setting the arpeggio range in octaves. The selected arpeggio will be played within specified number of octaves. Використовуйте цю ручку, щоб встановити діапазон арпеджіо (в октавах). Обраний тип арпеджіо охоплюватиме вказану кількість октав. - TIME - TIME + + CYCLE + ЦИКЛ - Arpeggio time: - Період арпеджіо: + + Cycle notes: + Зациклити ноти: - ms - мс + + note(s) + нота(и) - Use this knob for setting the arpeggio time in milliseconds. The arpeggio time specifies how long each arpeggio-tone should be played. - Регулювання періоду арпеджіо - час (в мілісекундах), який має звучати кожен тон арпеджіо. + + Jumps over n steps in the arpeggio and cycles around if we're over the note range. If the total note range is evenly divisible by the number of steps jumped over you will get stuck in a shorter arpeggio or even on one note. + - GATE - GATE + + SKIP + ПРОПУСК - Arpeggio gate: - Шлюз арпеджіо: + + Skip rate: + Частота пропуску: + + + % % - Use this knob for setting the arpeggio gate. The arpeggio gate specifies the percent of a whole arpeggio-tone that should be played. With this you can make cool staccato arpeggios. - Регулювання шлюзу арпеджіо, показує процентну частку кожного тону арпеджіо, яка буде відтворена. Простий спосіб створювати стаккато-арпеджіо. - - - Chord: - Акорд: - - - Direction: - Напрямок: - - - Mode: - Режим: - - - SKIP - - - - Skip rate: - - - + The skip function will make the arpeggiator pause one step randomly. From its start in full counter clockwise position and no effect it will gradually progress to full amnesia at maximum setting. + MISS - + ПРОПУСК + Miss rate: - + Частота пропуску: + The miss function will make the arpeggiator miss the intended note. - + Функція пропуску змусить арпеджіатор пропустити бажану ноту. - CYCLE - + + TIME + TIME - Cycle notes: - + + Arpeggio time: + Період арпеджіо: - note(s) - + + ms + мс - Jumps over n steps in the arpeggio and cycles around if we're over the note range. If the total note range is evenly divisible by the number of steps jumped over you will get stuck in a shorter arpeggio or even on one note. - + + Use this knob for setting the arpeggio time in milliseconds. The arpeggio time specifies how long each arpeggio-tone should be played. + Регулювання періоду арпеджіо - час (в мілісекундах), який має звучати кожен тон арпеджіо. + + + + GATE + GATE + + + + Arpeggio gate: + Шлюз арпеджіо: + + + + Use this knob for setting the arpeggio gate. The arpeggio gate specifies the percent of a whole arpeggio-tone that should be played. With this you can make cool staccato arpeggios. + Регулювання шлюзу арпеджіо, показує процентну частку кожного тону арпеджіо, яка буде відтворена. Простий спосіб створювати стаккато-арпеджіо. + + + + Chord: + Акорд: + + + + Direction: + Напрямок: + + + + Mode: + Режим: InstrumentFunctionNoteStacking + octave Октава + + Major Мажорний + Majb5 Majb5 + minor мінорний + minb5 minb5 + sus2 sus2 + sus4 sus4 + aug aug + augsus4 augsus4 + tri tri + 6 6 + 6sus4 6sus4 + 6add9 6add9 + m6 m6 + m6add9 m6add9 + 7 7 + 7sus4 7sus4 + 7#5 7#5 + 7b5 7b5 + 7#9 7#9 + 7b9 7b9 + 7#5#9 7#5#9 + 7#5b9 7#5b9 + 7b5b9 7b5b9 + 7add11 7add11 + 7add13 7add13 + 7#11 7#11 + Maj7 Maj7 + Maj7b5 Maj7b5 + Maj7#5 Maj7#5 + Maj7#11 Maj7#11 + Maj7add13 Maj7add13 + m7 m7 + m7b5 m7b5 + m7b9 m7b9 + m7add11 m7add11 + m7add13 m7add13 + m-Maj7 m-Maj7 + m-Maj7add11 m-Maj7add11 + m-Maj7add13 m-Maj7add13 + 9 9 + 9sus4 9sus4 + add9 add9 + 9#5 9#5 + 9b5 9b5 + 9#11 9#11 + 9b13 9b13 + Maj9 Maj9 + Maj9sus4 Maj9sus4 + Maj9#5 Maj9#5 + Maj9#11 Maj9#11 + m9 m9 + madd9 madd9 + m9b5 m9b5 + m9-Maj7 m9-Maj7 + 11 11 + 11b9 11b9 + Maj11 Maj11 + m11 m11 + m-Maj11 m-Maj11 + 13 13 + 13#9 13#9 + 13b9 13b9 + 13b5b9 13b5b9 + Maj13 Maj13 + m13 m13 + m-Maj13 m-Maj13 + Harmonic minor Гармонійний мінор + Melodic minor Мелодійний мінор + Whole tone Цілий тон + Diminished Понижений + Major pentatonic Пентатонік major + Minor pentatonic Пентатонік major + Jap in sen Япон in sen + Major bebop Major Бібоп + Dominant bebop Домінтний бібоп + Blues Блюз + Arabic Арабська + Enigmatic Загадкова + Neopolitan Неаполітанська + Neopolitan minor Неаполітанський мінор + Hungarian minor Угорський мінор + Dorian Дорійська - Phrygolydian - Фруголідійська + + Phrygian + Фрігійський + Lydian Лідійська + Mixolydian Міксолідійська + Aeolian Еолійська + Locrian Локріанська - Chords - Акорди - - - Chord type - Тип акорду - - - Chord range - Діапазон акорду - - + Minor Мінор + Chromatic Хроматична + Half-Whole Diminished Напів-зниження + 5 5 + Phrygian dominant - + Фрігійська домінанта + Persian - + Перська + + + + Chords + Акорди + + + + Chord type + Тип акорду + + + + Chord range + Діапазон акорду InstrumentFunctionNoteStackingView - RANGE - ДІАПАЗОН - - - Chord range: - Діапазон акорду: - - - octave(s) - Октав[а/и] - - - Use this knob for setting the chord range in octaves. The selected chord will be played within specified number of octaves. - Ця ручка змінює діапазон акорду, який буде містити вказане число октав. - - + STACKING Стиковка + Chord: Акорд: + + + RANGE + ДІАПАЗОН + + + + Chord range: + Діапазон акорду: + + + + octave(s) + Октав[а/и] + + + + Use this knob for setting the chord range in octaves. The selected chord will be played within specified number of octaves. + Ця ручка змінює діапазон акорду, який буде містити вказане число октав. + InstrumentMidiIOView + ENABLE MIDI INPUT УВІМК MIDI ВХІД + + CHANNEL CHANNEL + + VELOCITY VELOCITY + ENABLE MIDI OUTPUT УВІМК MIDI ВИВІД + PROGRAM PROGRAM - MIDI devices to receive MIDI events from - MiDi пристрої-джерела подій - - - MIDI devices to send MIDI events to - MiDi пристрої для відправки подій на них - - + NOTE NOTE + + MIDI devices to receive MIDI events from + MiDi пристрої-джерела подій + + + + MIDI devices to send MIDI events to + MiDi пристрої для відправки подій на них + + + CUSTOM BASE VELOCITY СВОЯ БАЗОВА ШВИДКІСТЬ + Specify the velocity normalization base for MIDI-based instruments at 100% note velocity Визначає базову швидкість нормальізаціі для MiDi інструментів при гучності ноти 100% + BASE VELOCITY БАЗОВА ШВИДКІСТЬ @@ -3142,10 +3903,12 @@ You can remove and move FX channels in the context menu, which is accessed by ri InstrumentMiscView + MASTER PITCH ОСНОВНА ТОНАЛЬНІСТЬ + Enables the use of Master Pitch Включає використання основної тональності @@ -3153,126 +3916,158 @@ You can remove and move FX channels in the context menu, which is accessed by ri InstrumentSoundShaping + VOLUME VOLUME + Volume Гучність + CUTOFF CUTOFF + + Cutoff frequency Зріз частоти + RESO RESO + Resonance Резонанс + Envelopes/LFOs - Огибание/LFO + Обвідні/LFO + Filter type Тип фільтру + Q/Resonance Кіл./Резонансу + LowPass Низ.ЧФ + HiPass Вис.ЧФ + BandPass csg Серед.ЧФ csg + BandPass czpg Серед.ЧФ czpg + Notch Смуго-загороджуючий + Allpass Всі проходять + Moog Муг + 2x LowPass 2х Низ.ЧФ + RC LowPass 12dB RC Низ.ЧФ 12дБ + RC BandPass 12dB RC Серед.ЧФ 12 дБ + RC HighPass 12dB RC Вис.ЧФ 12дБ + RC LowPass 24dB RC Низ.ЧФ 24дБ + RC BandPass 24dB RC Серед.ЧФ 24дБ + RC HighPass 24dB RC Вис.ЧФ 24дБ + Vocal Formant Filter Фільтр Вокальної форманти + 2x Moog 2x Муг + SV LowPass SV Низ.ЧФ + SV BandPass SV Серед.ЧФ + SV HighPass SV Вис.ЧФ + SV Notch SV Смуго-заг + Fast Formant Швидка форманта + Tripole Тріполі @@ -3280,51 +4075,63 @@ You can remove and move FX channels in the context menu, which is accessed by ri InstrumentSoundShapingView + TARGET ЦЕЛЬ + These tabs contain envelopes. They're very important for modifying a sound, in that they are almost always necessary for substractive synthesis. For example if you have a volume envelope, you can set when the sound should have a specific volume. If you want to create some soft strings then your sound has to fade in and out very softly. This can be done by setting large attack and release times. It's the same for other envelope targets like panning, cutoff frequency for the used filter and so on. Just monkey around with it! You can really make cool sounds out of a saw-wave with just some envelopes...! Ця вкладка дозволяє вам налаштувати обвідні. Вони дуже важливі для налаштування звучання. Наприклад, за допомогою обвідної гучності ви можете задати залежність гучності звучання від часу. Якщо вам знадобиться емулювати м'які струнні, просто задайте більше часу наростання і зникнення звуку. За допомогою обвідних і низькочастотного осциллятора (LFO) ви в кілька кліків миші зможете створити просто неймовірні звуки! + FILTER ФИЛЬТР + Here you can select the built-in filter you want to use for this instrument-track. Filters are very important for changing the characteristics of a sound. Здесь вы можете выбрать фильтр для дорожки этого инструмента. Фильтры могут довольно сильно менять звучание. - Hz - Гц - - - Use this knob for setting the cutoff frequency for the selected filter. The cutoff frequency specifies the frequency for cutting the signal by a filter. For example a lowpass-filter cuts all frequencies above the cutoff frequency. A highpass-filter cuts all frequencies below cutoff frequency, and so on... - Эта ручка устанавливает частоту среза для выбранного фильтра. К примеру, ФНЧ будет срезать сигнал на частотах выше частоты среза, полосно-пропускающий фильтр будет хорошо пропускать сигнал только на заданной частоте и так далее... - - - RESO - РЕЗО - - - Resonance: - Резонанс: - - - Use this knob for setting Q/Resonance for the selected filter. Q/Resonance tells the filter how much it should amplify frequencies near Cutoff-frequency. - Эта ручка задаёт количество резонанса для фильтра, этим определяется насколько нужно усилить ближайшие к отрезанным частоты. - - + FREQ ЧАСТ + cutoff frequency: Срез частот: + + Hz + Гц + + + + Use this knob for setting the cutoff frequency for the selected filter. The cutoff frequency specifies the frequency for cutting the signal by a filter. For example a lowpass-filter cuts all frequencies above the cutoff frequency. A highpass-filter cuts all frequencies below cutoff frequency, and so on... + Эта ручка устанавливает частоту среза для выбранного фильтра. К примеру, ФНЧ будет срезать сигнал на частотах выше частоты среза, полосно-пропускающий фильтр будет хорошо пропускать сигнал только на заданной частоте и так далее... + + + + RESO + РЕЗО + + + + Resonance: + Підсилення: + + + + Use this knob for setting Q/Resonance for the selected filter. Q/Resonance tells the filter how much it should amplify frequencies near Cutoff-frequency. + Эта ручка задаёт количество резонанса для фильтра, этим определяется насколько нужно усилить ближайшие к отрезанным частоты. + + + Envelopes, LFOs and filters are not supported by the current instrument. Обвідні, LFO і фільтри не підтримуються цим інструментом. @@ -3332,85 +4139,107 @@ You can remove and move FX channels in the context menu, which is accessed by ri InstrumentTrack - unnamed_track - безіменна_доріжка - - - Volume - Гучність - - - Panning - Стерео - - - Pitch - Тональність - - - FX channel - Канал ЕФ - - - Default preset - Основна предустановка - - + With this knob you can set the volume of the opened channel. Регулювання гучності поточного каналу. + + + unnamed_track + безіменна_доріжка + + + Base note Опорна нота + + Volume + Гучність + + + + Panning + Стерео + + + + Pitch + Тональність + + + Pitch range Діапазон тональності + + FX channel + Канал ЕФ + + + Master Pitch Основна тональність + + + + Default preset + Основна предустановка + InstrumentTrackView + Volume Гучність + Volume: Гучність: + VOL ГУЧН + Panning Баланс + Panning: Баланс: + PAN БАЛ + MIDI MIDI + Input Вхід + Output Вихід + FX %1: %2 ЕФ %1: %2 @@ -3418,136 +4247,168 @@ You can remove and move FX channels in the context menu, which is accessed by ri InstrumentTrackWindow + GENERAL SETTINGS ОСНОВНІ НАЛАШТУВАННЯ - Instrument volume - Гучність інструменту - - - Volume: - Гучність: - - - VOL - ГУЧН - - - Panning - Баланс - - - Panning: - Стереобаланс: - - - PAN - БАЛ - - - Pitch - Тональність - - - Pitch: - Тональність: - - - cents - відсотків - - - PITCH - ТОН - - - FX channel - Канал ЕФ - - - FX - ЕФ - - - Save preset - Зберегти передустановку - - - XML preset file (*.xpf) - XML файл налаштувань (*.xpf) - - - Pitch range (semitones) - Діапазон тональності (півтону) - - - RANGE - ДІАПАЗОН - - - Save current instrument track settings in a preset file - Зберегти поточну інструментаьную доріжку в файл предустановок - - - Click here, if you want to save current instrument track settings in a preset file. Later you can load this preset by double-clicking it in the preset-browser. - Нитисніть тут, щоб зберегти налаштування поточної інстр. доріжки в файл предустановок. Пізніше можна завантажити цю передустановку подвійним кліком в браузері предустановок. - - + Use these controls to view and edit the next/previous track in the song editor. Використовуйте ці елементи керування для перегляду і редагування наступного/попереднього треку в музичному редакторі. + + Instrument volume + Гучність інструменту + + + + Volume: + Гучність: + + + + VOL + ГУЧН + + + + Panning + Баланс + + + + Panning: + Стереобаланс: + + + + PAN + БАЛ + + + + Pitch + Тональність + + + + Pitch: + Тональність: + + + + cents + відсотків + + + + PITCH + ТОН + + + + Pitch range (semitones) + Діапазон тональності (півтону) + + + + RANGE + ДІАПАЗОН + + + + FX channel + Канал ЕФ + + + + FX + ЕФ + + + + Save current instrument track settings in a preset file + Зберегти поточну інструментаьную доріжку в файл предустановок + + + + Click here, if you want to save current instrument track settings in a preset file. Later you can load this preset by double-clicking it in the preset-browser. + Нитисніть тут, щоб зберегти налаштування поточної інстр. доріжки в файл предустановок. Пізніше можна завантажити цю передустановку подвійним кліком в браузері предустановок. + + + SAVE ЗБЕРЕГТИ + Envelope, filter & LFO - + Обвідна, фільтр & LFO + Chord stacking & arpeggio - + Укладання акордів & арпеджіо + Effects - + Ефекти + MIDI settings Параметри MIDI + Miscellaneous - + Різне + + Save preset + Зберегти передустановку + + + + XML preset file (*.xpf) + XML файл налаштувань (*.xpf) + + + Plugin - + Модуль Knob + Set linear Встановити лінійний + Set logarithmic Встановити логарифмічний - Please enter a new value between %1 and %2: - Введіть нове значення від %1 до %2: - - + Please enter a new value between -96.0 dBFS and 6.0 dBFS: Введіть нове значення від -96,0 дБFS до 6,0 дБFS: + + + Please enter a new value between %1 and %2: + Введіть нове значення від %1 до %2: + LadspaControl + Link channels Зв'язати канали @@ -3555,10 +4416,12 @@ You can remove and move FX channels in the context menu, which is accessed by ri LadspaControlDialog + Link Channels Зв'язати канали + Channel Канал @@ -3566,14 +4429,17 @@ You can remove and move FX channels in the context menu, which is accessed by ri LadspaControlView + Link channels Зв'язати канали + Value: Значення: + Sorry, no help available. Вибачте, довідки немає. @@ -3581,6 +4447,7 @@ You can remove and move FX channels in the context menu, which is accessed by ri LadspaEffect + Unknown LADSPA plugin %1 requested. Запитаний невідомий модуль LADSPA «%1». @@ -3588,6 +4455,7 @@ You can remove and move FX channels in the context menu, which is accessed by ri LcdSpinBox + Please enter a new value between %1 and %2: Введіть нове значення від %1 до %2: @@ -3595,18 +4463,26 @@ You can remove and move FX channels in the context menu, which is accessed by ri LeftRightNav + + + Previous Попередній + + + Next Наступний + Previous (%1) Попередній (%1) + Next (%1) Наступний (%1) @@ -3614,30 +4490,37 @@ You can remove and move FX channels in the context menu, which is accessed by ri LfoController + LFO Controller Контролер LFO + Base value Основне значення + Oscillator speed Швидкість хвилі + Oscillator amount Розмір хвилі + Oscillator phase Фаза хвилі + Oscillator waveform Форма хвилі + Frequency Multiplier Множник частоти @@ -3645,115 +4528,142 @@ You can remove and move FX channels in the context menu, which is accessed by ri LfoControllerDialog + LFO LFO + LFO Controller Контролер LFO + BASE БАЗА + Base amount: - Кіл-ть бази: + Базове значення: + todo доробити + SPD ШВИД + LFO-speed: Швидкість LFO: + Use this knob for setting speed of the LFO. The bigger this value the faster the LFO oscillates and the faster the effect. Ця ручка встановлює швидкість LFO. Чим більше значення, тим більша частота осциллятора. + + AMNT + ГЛИБ + + + Modulation amount: Кількість модуляції: + Use this knob for setting modulation amount of the LFO. The bigger this value, the more the connected control (e.g. volume or cutoff-frequency) will be influenced by the LFO. Ця ручка встановлює глибину модуляції для LFO. Чим більше значення, тим більшою мірою обрана характеристика (н-д, гучність або частота зрізу) буде залежати від ГНЧ (LFO). + PHS ФАЗА + Phase offset: Зсув фази: + degrees градуси + With this knob you can set the phase offset of the LFO. That means you can move the point within an oscillation where the oscillator begins to oscillate. For example if you have a sine-wave and have a phase-offset of 180 degrees the wave will first go down. It's the same with a square-wave. Ця ручка встановлює початкову фазу НизькоЧастотного Осциллятора (LFO), т. б. Точку, з якої осциллятор починає виробляти сигнал. Наприклад, якщо ви задали синусоїдальну форму сигналу і початкову фазу 180º, хвиля спочатку піде вниз, а не вгору, так само як і для квадратної хвилі. + Click here for a sine-wave. Синусоїда. + Click here for a triangle-wave. - Трикутник. + Згенерувати трикутний сигнал. + Click here for a saw-wave. - Зигзаг. + Згенерувати зигзаг. + Click here for a square-wave. - Квадрат. + Згенерувати квадратний сигнал. + + Click here for a moog saw-wave. + Натисніть для зигзагоподібної муг-хвилі. + + + Click here for an exponential wave. - Експонента. + Генерувати експонентний сигнал. + Click here for white-noise. - Білий шум. + Згенерувати білий шум. + Click here for a user-defined shape. Double click to pick a file. Натисніть тут для визначення своєї форми. Подвійне натискання для вибору файлу. - - Click here for a moog saw-wave. - Натисніть для зигзагоподібної муг-хвилі. - - - AMNT - ГЛИБ - LmmsCore + Generating wavetables Генерування синтезатора звукозаписів + Initializing data structures Ініціалізація структур даних + Opening audio and midi devices Відкриття аудіо та міді пристроїв + Launching mixer threads Запуск потоків міксера @@ -3761,397 +4671,501 @@ Double click to pick a file. MainWindow + + Configuration file + Файл налаштувань + + + + Error while parsing configuration file at line %1:%2: %3 + Помилка під час обробки файлу налаштувань в рядку %1:%2:%3 + + + + Could not open file + Не можу відкрити файл + + + + Could not open file %1 for writing. +Please make sure you have write permission to the file and the directory containing the file and try again! + Не вдалось відкрити файл %1 для запису. +Перевірте, чи маєте ви права на запис файлу і каталог що його містить і спробуйте знову! + + + + Project recovery + Відновлення проекту + + + + There is a recovery file present. It looks like the last session did not end properly or another instance of LMMS is already running. Do you want to recover the project of this session? + Присутній файл відновлення. Схоже, остання сесія не закінчилася належним чином або інший екземпляр LMMS вже запущений. Ви хочете, відновити проект цієї сесії? + + + + + + Recover + Відновлення + + + + Recover the file. Please don't run multiple instances of LMMS when you do this. + Відновлення файлу. Будь ласка, не запускайте кілька копій LMMS під час цієї операції. + + + + + + Discard + Відкинути + + + + Launch a default session and delete the restored files. This is not reversible. + Запуск за замовчуванням з видаленням файла відновлення. Ця дія не відворотня. + + + + Version %1 + Версія %1 + + + + Preparing plugin browser + Підготовка браузера плагінів + + + + Preparing file browsers + Підготовка переглядача файлів + + + + My Projects + Мої проекти + + + + My Samples + Мої записи + + + + My Presets + Мої передустановки + + + + My Home + Моя домашня тека + + + + Root directory + Кореневий каталог + + + + Volumes + Гучності + + + + My Computer + Мій комп'ютер + + + + Loading background artwork + Завантаження фонового зображення + + + + &File + &Файл + + + &New &N Новий + + New from template + Новий проект по шаблону + + + &Open... &O Відкрити... + + &Recently Opened Projects + &Нещодавно відкриті проекти + + + &Save &S Зберегти + Save &As... &A Зберегти як... + + Save as New &Version + Зберегти як нову &Версію + + + + Save as default template + Зберегти як шаблон за замовчуванням + + + Import... Імпорт... + E&xport... &X Експорт ... + + E&xport Tracks... + &Експортувати треки ... + + + + Export &MIDI... + Експорт в &MIDI ... + + + &Quit &Q Вийти + &Edit &E Редагування + + Undo + Скасувати + + + + Redo + Повторити + + + Settings Параметри + + &View + &V Перегляд + + + &Tools &T Сервіс + &Help &H Довідка + + Online Help + Онлайн Допомога + + + Help Довідка - What's this? + + What's This? Що це? + About Про програму + Create new project Створити новий проект + Create new project from template Створити новий проект по шаблону + Open existing project Відкрити існуючий проект + Recently opened projects Нещодавні проекти + Save current project Зберегти поточний проект + Export current project Експорт проекту - Song Editor - Музичний редактор + + What's this? + Що це? + + Toggle metronome + Переключити метроном + + + + Show/hide Song-Editor + Показати/сховати музичний редактор + + + By pressing this button, you can show or hide the Song-Editor. With the help of the Song-Editor you can edit song-playlist and specify when which track should be played. You can also insert and move samples (e.g. rap samples) directly into the playlist. Показати чи сховати музичний редактор. З його допомогою ви можете редагувати композицію і задавати час відтворення кожної доріжки. Також ви можете вставляти і пересувати записи прямо у списку відтворення. - Beat+Bassline Editor - Редактор шаблонів + + Show/hide Beat+Bassline Editor + Показати/сховати ритм-бас редактор + By pressing this button, you can show or hide the Beat+Bassline Editor. The Beat+Bassline Editor is needed for creating beats, and for opening, adding, and removing channels, and for cutting, copying and pasting beat and bassline-patterns, and for other things like that. Показати чи сховати ритм-бас редактор. Він необхідний для установки ритму, відкриття, додавання і видалення каналів, а також вирізання, копіювання і вставки ритм-бас шаблонів і схожих речей. - Piano Roll - Нотний редактор + + Show/hide Piano-Roll + Показати/сховати нотний редактор + Click here to show or hide the Piano-Roll. With the help of the Piano-Roll you can edit melodies in an easy way. Запуск редатора нот. З його допомогою ви можете легко редагувати мелодії. - Automation Editor - Редактор автоматизації + + Show/hide Automation Editor + Показати/сховати редактор автоматизації + Click here to show or hide the Automation Editor. With the help of the Automation Editor you can edit dynamic values in an easy way. Показати / сховати вікно редактора автоматизації. З його допомогою ви можете легко редагувати динаміку обраних величин. - FX Mixer - Мікшер Ефектів + + Show/hide FX Mixer + Показати/сховати мікшер ЕФ + Click here to show or hide the FX Mixer. The FX Mixer is a very powerful tool for managing effects for your song. You can insert effects into different effect-channels. Сховати / показати мікшер ефектів. Він є потужним інструментом для управління ефектами. Ви можете вставляти ефекти в різні канали. - Project Notes - Примітки проекту + + Show/hide project notes + Показати/сховати замітки до проекту + Click here to show or hide the project notes window. In this window you can put down your project notes. Ця кнопка показує / ховає вікно з нотатками. У цьому вікні ви можете поміщати будь-які коментарі до своєї композиції. - Controller Rack - Стійка контролерів + + Show/hide controller rack + Показати/сховати керування контролерами + Untitled Без назви + + Recover session. Please save your work! + Відновлення сесії. Будь ласка, збережіть свою роботу! + + + LMMS %1 LMMS %1 + + Recovered project not saved + Відновлений проект не збережено + + + + This project was recovered from the previous session. It is currently unsaved and will be lost if you don't save it. Do you want to save it now? + Цей проект буво відновлено з попередньої сесії. В даний час він не збережений і буде втрачений, якщо ви його не збережете. Ви хочете, зберегти його зараз? + + + Project not saved Проект не збережений + The current project was modified since last saving. Do you want to save it now? Проект був змінений. Зберегти його зараз? + + Open Project + Відкрити проект + + + + LMMS (*.mmp *.mmpz) + LMMS (*.mmp *.mmpz) + + + + Save Project + Зберегти проект + + + + LMMS Project + LMMS проект + + + + LMMS Project Template + Шаблон LMMS проекту + + + + Save project template + Зберегти шаблон проекту + + + + Overwrite default template? + Переписати шаблон за замовчуванням? + + + + This will overwrite your current default template. + Це перезапише поточний шаблон за замовчуванням. + + + Help not available Довідка недоступна + Currently there's no help available in LMMS. Please visit http://lmms.sf.net/wiki for documentation on LMMS. Поки що довідка для LMMS не написана. Ймовірно, Ви зможете знайти потрібні матеріали на http://lmms.sf.net/wiki. - LMMS (*.mmp *.mmpz) - LMMS (*.mmp *.mmpz) + + Song Editor + Музичний редактор - Version %1 - Версія %1 + + Beat+Bassline Editor + Редактор шаблонів - Configuration file - Файл налаштувань + + Piano Roll + Нотний редактор - Error while parsing configuration file at line %1:%2: %3 - Помилка під час обробки файлу налаштувань в рядку %1:%2:%3 + + Automation Editor + Редактор автоматизації - Volumes - Гучності + + FX Mixer + Мікшер Ефектів - Undo - Скасувати + + Project Notes + Примітки проекту - Redo - Повторити - - - My Projects - Мої проекти - - - My Samples - Мої записи - - - My Presets - Мої передустановки - - - My Home - Моя домашня тека - - - My Computer - Мій комп'ютер - - - &File - &Файл - - - &Recently Opened Projects - &Нещодавно відкриті проекти - - - Save as New &Version - Зберегти як нову &Версію - - - E&xport Tracks... - &Експортувати треки ... - - - Online Help - Онлайн Допомога - - - What's This? - Що це? - - - Open Project - Відкрити проект - - - Save Project - Зберегти проект - - - Project recovery - Відновлення проекту - - - There is a recovery file present. It looks like the last session did not end properly or another instance of LMMS is already running. Do you want to recover the project of this session? - Присутній файл відновлення. Схоже, остання сесія не закінчилася належним чином або інший екземпляр LMMS вже запущений. Ви хочете, відновити проект цієї сесії? - - - Recover - Відновлення - - - Recover the file. Please don't run multiple instances of LMMS when you do this. - Відновлення файлу. Будь ласка, не запускайте кілька копій LMMS під час цієї операції. - - - Discard - Відкинути - - - Launch a default session and delete the restored files. This is not reversible. - Запуск за замовчуванням з видаленням файла відновлення. Ця дія не відворотня. - - - Preparing plugin browser - Підготовка браузера плагінів - - - Preparing file browsers - Підготовка переглядача файлів - - - Root directory - Кореневий каталог - - - Loading background artwork - Завантаження фонового зображення - - - New from template - Новий проект по шаблону - - - Save as default template - Зберегти як шаблон за замовчуванням - - - &View - &V Перегляд - - - Toggle metronome - Переключити метроном - - - Show/hide Song-Editor - Показати/сховати музичний редактор - - - Show/hide Beat+Bassline Editor - Показати/сховати ритм-бас редактор - - - Show/hide Piano-Roll - Показати/сховати нотний редактор - - - Show/hide Automation Editor - Показати/сховати редактор автоматизації - - - Show/hide FX Mixer - Показати/сховати мікшер ЕФ - - - Show/hide project notes - Показати/сховати замітки до проекту - - - Show/hide controller rack - Показати/сховати керування контролерами - - - Recover session. Please save your work! - Відновлення сесії. Будь ласка, збережіть свою роботу! - - - Recovered project not saved - Відновлений проект не збережено - - - This project was recovered from the previous session. It is currently unsaved and will be lost if you don't save it. Do you want to save it now? - Цей проект буво відновлено з попередньої сесії. В даний час він не збережений і буде втрачений, якщо ви його не збережете. Ви хочете, зберегти його зараз? - - - LMMS Project - LMMS проект - - - LMMS Project Template - Шаблон LMMS проекту - - - Overwrite default template? - Переписати шаблон за замовчуванням? - - - This will overwrite your current default template. - Це перезапише поточний шаблон за замовчуванням. - - - Smooth scroll - Плавне прокручування - - - Enable note labels in piano roll - Включити позначення нот у музичному редакторі - - - Save project template - + + Controller Rack + Стійка контролерів + Volume as dBFS Відображати гучність в децибелах - Could not open file - Не можу відкрити файл + + Smooth scroll + Плавне прокручування - Could not open file %1 for writing. -Please make sure you have write permission to the file and the directory containing the file and try again! - - - - Export &MIDI... - Експорт в &MIDI ... + + Enable note labels in piano roll + Включити позначення нот у музичному редакторі MeterDialog + + Meter Numerator Шкала чисел + + Meter Denominator Шкала поділів + TIME SIG ПЕРІОД @@ -4159,10 +5173,12 @@ Please make sure you have write permission to the file and the directory contain MeterModel + Numerator Чисельник + Denominator Знаменник @@ -4170,10 +5186,12 @@ Please make sure you have write permission to the file and the directory contain MidiController + MIDI Controller Контролер MIDI + unnamed_midi_controller нерозпізнаний міді контролер @@ -4181,19 +5199,24 @@ Please make sure you have write permission to the file and the directory contain MidiImport + + Setup incomplete Установку не завершено + You do not have set up a default soundfont in the settings dialog (Edit->Settings). Therefore no sound will be played back after importing this MIDI file. You should download a General MIDI soundfont, specify it in settings dialog and try again. Ви не встановили SoundFont за замовчуванням в налаштуваннях (Правка-> Налаштування), тому після імпорту міді файлу звук відтворюватися не буде. Вам слід завантажити основний MiDi SoundFont, вказати його в налаштуваннях і спробувати знову. + You did not compile LMMS with support for SoundFont2 player, which is used to add default sound to imported MIDI files. Therefore no sound will be played back after importing this MIDI file. Ви не увімкнули підтримку програвача SoundFont2 при компіляції LMMS, він використовується для додавання основного звуку в імпортовані Міді файли, тому після імпорту цього міді файлу звуку не буде. + Track Трек @@ -4201,66 +5224,80 @@ Please make sure you have write permission to the file and the directory contain MidiJack + JACK server down When JACK(JACK Audio Connection Kit) disconnects, it will show the following message (title) JACK-сервер не доступний + The JACK server seems to be shuted down. When JACK(JACK Audio Connection Kit) disconnects, it will show the following message (dialog message) - + Здається, сервер JACK відключений. MidiPort + Input channel Вхід + Output channel Вихід + Input controller Контролер входу + Output controller Контролер виходу + Fixed input velocity Постійна швидкість введення + Fixed output velocity Постійна швидкість виведення - Output MIDI program - Програма для виведення MiDi - - - Receive MIDI-events - Приймати події MIDI - - - Send MIDI-events - Відправляти події MIDI - - + Fixed output note Постійний вихід нот + + Output MIDI program + Програма для виведення MiDi + + + Base velocity Базова швидкість + + + Receive MIDI-events + Приймати події MIDI + + + + Send MIDI-events + Відправляти події MIDI + MidiSetupWidget + DEVICE ПРИСТРІЙ @@ -4268,474 +5305,595 @@ Please make sure you have write permission to the file and the directory contain MonstroInstrument + Osc 1 Volume Гучність осциллятора 1 + Osc 1 Panning Баланс осциллятора 1 + Osc 1 Coarse detune Грубе підстроювання осциллятора 1 + Osc 1 Fine detune left Точне підстроювання лівого каналу осциллятора 1 + Osc 1 Fine detune right Точне підстроювання правого каналу осциллятора 1 + Osc 1 Stereo phase offset Зміщення стерео-фази осциллятора 1 + Osc 1 Pulse width Довжина імпульсу осциллятора 1 + Osc 1 Sync send on rise Синхронізація підйому осциллятора 1 + Osc 1 Sync send on fall Синхронізація падіння осциллятора 1 + Osc 2 Volume Гучність осциллятора 2 + Osc 2 Panning Баланс осциллятора 2 + Osc 2 Coarse detune Грубе підстроювання осциллятора 2 + Osc 2 Fine detune left Точне підстроювання лівого каналу осциллятора 2 + Osc 2 Fine detune right Точне підстроювання правого каналу осциллятора 2 + Osc 2 Stereo phase offset Зміщення стерео-фази осциллятора 2 + Osc 2 Waveform Форма сигналу осциллятора 2 + Osc 2 Sync Hard Жорстка синхронізація осциллятора 2 + Osc 2 Sync Reverse Верерс синхронізація осциллятора 2 + Osc 3 Volume Гучність осциллятора 3 + Osc 3 Panning Баланс осциллятора 3 + Osc 3 Coarse detune Грубе підстроювання осциллятора 3 + Osc 3 Stereo phase offset Зміщення стерео-фази осциллятора 3 + Osc 3 Sub-oscillator mix Змішення суб-генератора осциллятора 3 + Osc 3 Waveform 1 Форма 1 сигналу осциллятора 3 + Osc 3 Waveform 2 Форма 2 сигналу осциллятора 3 + Osc 3 Sync Hard Жорстка синхронізація осциллятора 3 + Osc 3 Sync Reverse Верерс синхронізація осциллятора 3 + LFO 1 Waveform Форма сигналу LFO 1 + LFO 1 Attack Вступ LFO 1 + LFO 1 Rate Темп LFO 1 + LFO 1 Phase Фаза LFO 1 + LFO 2 Waveform Форма сигналу LFO 2 + LFO 2 Attack Вступ LFO 2 + LFO 2 Rate Темп LFO 2 + LFO 2 Phase Фаза LFO 2 + Env 1 Pre-delay Затримка обвідної 1 + Env 1 Attack Вступ обвідної 1 + Env 1 Hold Утримання обвідної 1 + Env 1 Decay Згасання обвідної 1 + Env 1 Sustain Витримка обвідної 1 + Env 1 Release Зменшення обвідної 1 + Env 1 Slope Нахил обвідної 1 + Env 2 Pre-delay Затримка обвідної 2 + Env 2 Attack Вступ обвідної 2 + Env 2 Hold Утримання обвідної 2 + Env 2 Decay Згасання обвідної 2 + Env 2 Sustain Витримка обвідної 2 + Env 2 Release Зменшення обвідної 2 + Env 2 Slope Нахил обвідної 2 + Osc2-3 modulation Модуляція осцилляторів 2-3 + Selected view Перегляд обраного + Vol1-Env1 Гучн1-Обв1 + Vol1-Env2 Гучн1-Обв2 + Vol1-LFO1 Гучн1-LFO1 + Vol1-LFO2 Гучн1-LFO2 + Vol2-Env1 Гучн2-Обв1 + Vol2-Env2 Гучн2-Обв2 + Vol2-LFO1 Гучн2-LFO1 + Vol2-LFO2 Гучн2-LFO2 + Vol3-Env1 Гучн3-Обв1 + Vol3-Env2 Гучн3-Обв2 + Vol3-LFO1 Гучн3-LFO1 + Vol3-LFO2 Гучн3-LFO2 + Phs1-Env1 Фаз1-Обв1 + Phs1-Env2 Фаз1-Обв2 + Phs1-LFO1 Фаз1-LFO1 + Phs1-LFO2 Фаз1-LFO2 + Phs2-Env1 Фаз2-Обв1 + Phs2-Env2 Фаз2-Обв2 + Phs2-LFO1 Фаз2-LFO1 + Phs2-LFO2 Фаз2-LFO2 + Phs3-Env1 Фаз3-Обв1 + Phs3-Env2 Фаз3-Обв2 + Phs3-LFO1 Фаз3-LFO1 + Phs3-LFO2 Фаз3-LFO2 + Pit1-Env1 Тон1-Обв1 + Pit1-Env2 Тон1-Обв2 + Pit1-LFO1 Тон1-LFO1 + Pit1-LFO2 Тон1-LFO2 + Pit2-Env1 Тон2-Обв1 + Pit2-Env2 Тон2-Обв2 + Pit2-LFO1 Тон2-LFO1 + Pit2-LFO2 Тон2-LFO2 + Pit3-Env1 Тон3-Обв1 + Pit3-Env2 Тон3-Обв2 + Pit3-LFO1 Тон3-LFO1 + Pit3-LFO2 Тон3-LFO2 + PW1-Env1 PW1-Обв1 + PW1-Env2 PW1-Обв2 + PW1-LFO1 PW1-LFO1 + PW1-LFO2 PW1-LFO2 + Sub3-Env1 Sub3-Обв1 + Sub3-Env2 Sub3-Обв2 + Sub3-LFO1 Sub3-LFO1 + Sub3-LFO2 Sub3-LFO2 + + Sine wave Синусоїда + Bandlimited Triangle wave Трикутна хвиля з обмеженою смугою + Bandlimited Saw wave Зигзаг хвиля з обмеженою смугою + Bandlimited Ramp wave Спадаюча хвиля з обмеженою смугою + Bandlimited Square wave Квадратна хвиля з обмеженою смугою + Bandlimited Moog saw wave Муг-зигзаг хвиля з обмеженою смугою + + Soft square wave М'яка прямокутна хвиля + Absolute sine wave Абсолютна синусоїдна хвиля + + Exponential wave Експоненціальна хвиля + White noise Білий шум + Digital Triangle wave Цифрова трикутна хвиля + Digital Saw wave Цифрова зигзаг хвиля + Digital Ramp wave Цифрова спадна хвиля + Digital Square wave Цифрова квадратна хвиля + Digital Moog saw wave Цифрова Муг-зигзаг хвиля + Triangle wave Трикутна хвиля + Saw wave Зигзаг + Ramp wave Спадна хвиля + Square wave Квадратна хвиля + Moog saw wave Муг-зигзаг хвиля + Abs. sine wave Синусоїда по модулю + Random Випадково + Random smooth Випадкове зглажування @@ -4743,10 +5901,12 @@ Please make sure you have write permission to the file and the directory contain MonstroView + Operators view Операторский вид + The Operators view contains all the operators. These include both audible operators (oscillators) and inaudible operators, or modulators: Low-frequency oscillators and Envelopes. Knobs and other widgets in the Operators view have their own what's this -texts, so you can get more specific help for them that way. @@ -4755,10 +5915,12 @@ Knobs and other widgets in the Operators view have their own what's this -t Регулятори й інші віджети в операторському вигляді мають свої підписи "Що це?", Таким чином по ним можна отримати більш детальну довідку. + Matrix view Матричний вигляд + The Matrix view contains the modulation matrix. Here you can define the modulation relationships between the various operators: Each audible operator (oscillators 1-3) has 3-4 properties that can be modulated by any of the modulators. Using more modulations consumes more CPU power. The view is divided to modulation targets, grouped by the target oscillator. Available targets are volume, pitch, phase, pulse width and sub-osc ratio. Note: some targets are specific to one oscillator only. @@ -4771,80 +5933,266 @@ Each modulation target has 4 knobs, one for each modulator. By default the knobs Кожна ціль модуляції має 4 регулятори, по одному на кожен модулятор. За замовчуванням регулятори встановлені на 0, тобто без модуляції. Включення регуляторів на 1 веде до того, що модулятор впливає на ціль модуляції на стільки на скільки це можливо. Включення його в -1 робить те ж, але зі зворотньою модуляцією. + + + + Volume + Гучність + + + + + + Panning + Баланс + + + + + + Coarse detune + Грубе підстроювання + + + + + + semitones + півтон(а,ів) + + + + + Finetune left + Точне настроювання лівого каналу + + + + + + + cents + відсотків + + + + + Finetune right + Точне настроювання правого каналу + + + + + + Stereo phase offset + Зміщення стерео-фази + + + + + + + + deg + град + + + + Pulse width + Довжина імпульсу + + + + Send sync on pulse rise + Відправляти синхронізацію на підйомі імпульсу + + + + Send sync on pulse fall + Відправити синхронізацію на падінні пульсу + + + + Hard sync oscillator 2 + Жорстка синхронізація осциллятора 2 + + + + Reverse sync oscillator 2 + Верерс синхронізація осциллятора 2 + + + + Sub-osc mix + Мікс суб-осциляторів + + + + Hard sync oscillator 3 + Жорстка синхронізація осциллятора 3 + + + + Reverse sync oscillator 3 + Верерс синхронізація осциллятора 3 + + + + + + + Attack + Вступ + + + + + Rate + Частота вибірки + + + + + Phase + Фаза + + + + + Pre-delay + Передзатримка + + + + + Hold + Утримання + + + + + Decay + Згасання + + + + + Sustain + Витримка + + + + + Release + Зменшення + + + + + Slope + Нахил + + + Mix Osc2 with Osc3 Змішати Осц2 з Осц3 + Modulate amplitude of Osc3 with Osc2 Модулювати амплітуду осциллятора 3 сигналом з осц2 + Modulate frequency of Osc3 with Osc2 Модулювати частоту осциллятора 3 сигналом з осц2 + Modulate phase of Osc3 with Osc2 Модулювати фазу Осц3 осциллятором2 + The CRS knob changes the tuning of oscillator 1 in semitone steps. Регулятор CRS змінює налаштування осциллятора 1 у розмірі півтону. + The CRS knob changes the tuning of oscillator 2 in semitone steps. Регулятор CRS змінює налаштування осциллятора 2 у розмірі півтону. + The CRS knob changes the tuning of oscillator 3 in semitone steps. Регулятор CRS змінює налаштування осциллятора 3 у розмірі півтону. + + + + FTL and FTR change the finetuning of the oscillator for left and right channels respectively. These can add stereo-detuning to the oscillator which widens the stereo image and causes an illusion of space. FTL і FTR змінюють підстроювання осциллятора для лівого і правого каналів відповідно. Вони можуть додати стерео розстроювання осциллятора, яке розширює стерео картину і створює ілюзію космосу. + + + The SPO knob modifies the difference in phase between left and right channels. Higher difference creates a wider stereo image. Регулятор SPO змінює фазову різницю між лівим і правим каналами. Висока різниця створює більш широку стерео картину. + The PW knob controls the pulse width, also known as duty cycle, of oscillator 1. Oscillator 1 is a digital pulse wave oscillator, it doesn't produce bandlimited output, which means that you can use it as an audible oscillator but it will cause aliasing. You can also use it as an inaudible source of a sync signal, which can be used to synchronize oscillators 2 and 3. PW регулятор контролює ширину пульсацій, також відому як робочий цикл осциллятора 1. Осциллятор 1 це цифровий імпульсний хвильовий генератор, він не відтворює сигнал з обмеженою смугою, це означає, що його можна використовувати як чутний осциллятор, але це призведе до накладення сигналів (або згладжування) . Його можна використовувати й як не чутне джерело синхронізуючого сигналу, для використання в синхронізації осцилляторів 2 і 3. + Send Sync on Rise: When enabled, the Sync signal is sent every time the state of oscillator 1 changes from low to high, ie. when the amplitude changes from -1 to 1. Oscillator 1's pitch, phase and pulse width may affect the timing of syncs, but its volume has no effect on them. Sync signals are sent independently for both left and right channels. Надсилати синхронізацію при підвищенні: при включенні, сигнал синхронізації надсилається кожен раз коли стан осциллятора 1 змінюється з низького на високий, тобто коли амплітуда змінюється від -1 до 1. Тон осциллятора 1, фаза і ширина пульсацій може впливати на час синхронізації, але гучність не має ефекту. Сигнал синхронізації надсилається незалежно для лівого і правого каналів. + Send Sync on Fall: When enabled, the Sync signal is sent every time the state of oscillator 1 changes from high to low, ie. when the amplitude changes from 1 to -1. Oscillator 1's pitch, phase and pulse width may affect the timing of syncs, but its volume has no effect on them. Sync signals are sent independently for both left and right channels. Надсилати синхронізацію при зниженні: при включенні, сигнал синхронізації надсилається кожен раз коли стан осциллятора 1 змінюється з виского на низьке, тобто коли амплітуда змінюється від 1 до -1. Тон осциллятора 1, фаза і ширина пульсацій може впливати на час синхронізації, але гучність не має ефекту. Сигнал синхронізації надсилається незалежно для лівого і правого каналів. + + Hard sync: Every time the oscillator receives a sync signal from oscillator 1, its phase is reset to 0 + whatever its phase offset is. Жорстка синхронізація: Кожен раз при отриманні осциллятором сигналу синхронізації від осциллятора 1, його фаза скидається до 0 + його межа фази, якою б вона не була. + + Reverse sync: Every time the oscillator receives a sync signal from oscillator 1, the amplitude of the oscillator gets inverted. Реверс синхронізація: Кожен раз при отриманні сигналу синхронізації від осциллятора 1, амплітуда осциллятора перевертається. + Choose waveform for oscillator 2. Вибрати форму хвилі для осциллятора 2. + Choose waveform for oscillator 3's first sub-osc. Oscillator 3 can smoothly interpolate between two different waveforms. Виберіть форму хвилі для першого додаткового осциллятора осциллятора 3. Осциллятор 3 може м'яко переходити між двома різними хвилями. + Choose waveform for oscillator 3's second sub-osc. Oscillator 3 can smoothly interpolate between two different waveforms. Виберіть форму хвилі для другого додаткового осциллятора осциллятора 3. Осциллятор 3 може м'яко переходити між двома різними хвилями. + The SUB knob changes the mixing ratio of the two sub-oscs of oscillator 3. Each sub-osc can be set to produce a different waveform, and oscillator 3 can smoothly interpolate between them. All incoming modulations to oscillator 3 are applied to both sub-oscs/waveforms in the exact same way. SUB змінює змішування двох дод осцилляторів осциллятора 3. Кожен дод. осц. може бути встановлений для створення різних хвиль і осциллятор 3 може м'яко переходити між ними. Усі вхідні модуляції для осциллятора 3 застосовуються на обидва дод.осц./хвилі одним і тим же чином. + In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. Mix mode means no modulation: the outputs of the oscillators are simply mixed together. @@ -4853,6 +6201,7 @@ Mix mode means no modulation: the outputs of the oscillators are simply mixed to Змішаний (Mix) режим означає без модуляції: виходи осцилляторів просто змішуються один з одним. + In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. AM means amplitude modulation: Oscillator 3's amplitude (volume) is modulated by oscillator 2. @@ -4861,6 +6210,7 @@ AM means amplitude modulation: Oscillator 3's amplitude (volume) is modulat AM режим значить Амплітуда Модуляції: Осциллятори 2 модулює амплітуду (гучність) осциллятора 3. + In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. FM means frequency modulation: Oscillator 3's frequency (pitch) is modulated by oscillator 2. The frequency modulation is implemented as phase modulation, which gives a more stable overall pitch than "pure" frequency modulation. @@ -4869,6 +6219,7 @@ FM means frequency modulation: Oscillator 3's frequency (pitch) is modulate FM (ЧМ) режим означає Частотна Модуляція: осциллятор 2 модулює частоту (pitch, тональність) осциллятора 3. Частота модуляції відбувається у фазі модуляції, яка дає більш стабільний загальний тон, ніж "чиста" частотна модуляція. + In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. PM means phase modulation: Oscillator 3's phase is modulated by oscillator 2. It differs from frequency modulation in that the phase changes are not cumulative. @@ -4877,6 +6228,7 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator PM (ФМ) режим означає Фазова Модуляція: Осциллятор 2 модулює фазу осциллятора 3. Це відрізняється від частотної модуляції тим, що зміни фаз не сумуються. + Select the waveform for LFO 1. "Random" and "Random smooth" are special waveforms: they produce random output, where the rate of the LFO controls how often the state of the LFO changes. The smooth version interpolates between these states with cosine interpolation. These random modes can be used to give "life" to your presets - add some of that analog unpredictability... Виберіть форму хвилі для LFO 1 (НизькоЧастотнийГенератор). @@ -4884,6 +6236,7 @@ PM (ФМ) режим означає Фазова Модуляція: Осцил Згладжена версія переходить між цими станами з косинусоїдальною інтерполяцією. Ці випадкові режими можуть бути використані, щоб дати "життя" вашим налаштуванням - додати трішки аналогової непередбачуваності ... + Select the waveform for LFO 2. "Random" and "Random smooth" are special waveforms: they produce random output, where the rate of the LFO controls how often the state of the LFO changes. The smooth version interpolates between these states with cosine interpolation. These random modes can be used to give "life" to your presets - add some of that analog unpredictability... Виберіть форму хвилі для LFO 2 (НизкоЧастотнийГенератор). @@ -4891,150 +6244,110 @@ PM (ФМ) режим означає Фазова Модуляція: Осцил Згладжена версія переходить між цими станами з косинусоїдальною інтерполяцією. Ці випадкові режими можуть бути використані, щоб дати "життя" вашим налаштуванням - додати трішки аналогової непередбачуваності ... + + Attack causes the LFO to come on gradually from the start of the note. Атака відповідає за плавність поведінки LFO від початку ноти. + + Rate sets the speed of the LFO, measured in milliseconds per cycle. Can be synced to tempo. Rate (Частота) встановлює швидкість LFO, вимірювану в мілісекундах за цикл. Може синхронізуватися з темпом. + + PHS controls the phase offset of the LFO. PHS контролює зсув фази LFO (НЧГ). + + PRE, or pre-delay, delays the start of the envelope from the start of the note. 0 means no delay. PRE передзатримка, затримує старт обвідної від початку ноти. 0 означає без затримки. + + ATT, or attack, controls how fast the envelope ramps up at start, measured in milliseconds. A value of 0 means instant. ATT атака контролює як швидко обвідна нарощується на старті, вимірюється в мілісекундах. Значення 0 означає миттєво. + + HOLD controls how long the envelope stays at peak after the attack phase. HOLD (УТРИМУВАТИ) контролює як довго обвідна залишається на піку після фази атаки. + + DEC, or decay, controls how fast the envelope falls off from its peak, measured in milliseconds it would take to go from peak to zero. The actual decay may be shorter if sustain is used. DEC (decay) згасання контролює як швидко обвідна спадає з пікового значення, вимірюється в мілісекундах, як довго буде йти з піку до нуля. Реальне загасання може бути коротшим, якщо використовується витримка. + + SUS, or sustain, controls the sustain level of the envelope. The decay phase will not go below this level as long as the note is held. SUS (sustain) витримка, контролює рівень обвідної. Загасання фази не піде нижче цього рівня поки нота утримується. + + REL, or release, controls how long the release is for the note, measured in how long it would take to fall from peak to zero. Actual release may be shorter, depending on at what phase the note is released. REL (release) відпускання контролює як довго нота відпускається, вимірюється в довготі падіння від піку до нуля. Реальне відпускання може бути коротшим, залежно від фази, в якій нота відпущена. + + The slope knob controls the curve or shape of the envelope. A value of 0 creates straight rises and falls. Negative values create curves that start slowly, peak quickly and fall of slowly again. Positive values create curves that start and end quickly, and stay longer near the peaks. Регулятор нахилу контролює криву або форму обвідної. Значення 0 створює прямі підйоми і спади. Від'ємні величини створюють криві з уповільненим початком, швидким піком і знову уповільненим спадом. Позитивні значення створюють криві які починаються і закінчуються швидко, але довше залишаються на піках. - Volume - Гучність - - - Panning - Баланс - - - Coarse detune - Грубе підстроювання - - - semitones - півтон(а,ів) - - - Finetune left - Точне настроювання лівого каналу - - - cents - відсотків - - - Finetune right - Точне настроювання правого каналу - - - Stereo phase offset - Зміщення стерео-фази - - - deg - град - - - Pulse width - Довжина імпульсу - - - Send sync on pulse rise - Відправляти синхронізацію на підйомі імпульсу - - - Send sync on pulse fall - Відправити синхронізацію на падінні пульсу - - - Hard sync oscillator 2 - Жорстка синхронізація осциллятора 2 - - - Reverse sync oscillator 2 - Верерс синхронізація осциллятора 2 - - - Sub-osc mix - Мікс суб-осциляторів - - - Hard sync oscillator 3 - Жорстка синхронізація осциллятора 3 - - - Reverse sync oscillator 3 - Верерс синхронізація осциллятора 3 - - - Attack - Вступ - - - Rate - Частота вибірки - - - Phase - Фаза - - - Pre-delay - Передзатримка - - - Hold - Утримання - - - Decay - Згасання - - - Sustain - Витримка - - - Release - Зменшення - - - Slope - Нахил - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Modulation amount Глибина модуляції @@ -5042,34 +6355,42 @@ PM (ФМ) режим означає Фазова Модуляція: Осцил MultitapEchoControlDialog + Length Довжина + Step length: Довжина кроку: + Dry Сухий + Dry Gain: Сухе підсилення: + Stages Етапи + Lowpass stages: НЧ етапи: + Swap inputs Обмін входами + Swap left and right input channel for reflections Дзеркальний обмін лівим і правим каналами @@ -5077,82 +6398,102 @@ PM (ФМ) режим означає Фазова Модуляція: Осцил NesInstrument + Channel 1 Coarse detune Грубе підстроювання 1 каналу + Channel 1 Volume Гучність 1 каналу + Channel 1 Envelope length Довжина обвідної 1 каналу + Channel 1 Duty cycle Робочий цикл 1 каналу + Channel 1 Sweep amount Кількість розгортки 1 каналу + Channel 1 Sweep rate Швидкість розгортки 1 каналу + Channel 2 Coarse detune Грубе підстроювання 2 каналу + Channel 2 Volume Гучність 2 каналу + Channel 2 Envelope length Довжина обвідної 2 каналу + Channel 2 Duty cycle Робочий цикл 2 каналу + Channel 2 Sweep amount Кількість розгортки 2 каналу + Channel 2 Sweep rate Швидкість розгортки 2 каналу + Channel 3 Coarse detune Грубе підстроювання 3 каналу + Channel 3 Volume Гучність 3 каналу + Channel 4 Volume Гучність 4 каналу + Channel 4 Envelope length Довжина обвідної 4 каналу + Channel 4 Noise frequency Частота шуму 4 каналу + Channel 4 Noise frequency sweep Частота розгортки шуму 4 каналу + Master volume Основна гучність + Vibrato Вібрато @@ -5160,114 +6501,155 @@ PM (ФМ) режим означає Фазова Модуляція: Осцил NesInstrumentView + + + + Volume Гучність + + + Coarse detune Грубе підстроювання + + + Envelope length Довжина обвідної + Enable channel 1 Увімкнути канал 1 + Enable envelope 1 Увімкнути обвідну 1 + Enable envelope 1 loop Увімкнти повтор обвідної 1 + Enable sweep 1 Увімкнути розгортку 1 + + Sweep amount Кількість розгортки + + Sweep rate Темп розгортки + + 12.5% Duty cycle 12.5% Робочого циклу + + 25% Duty cycle 25% Робочого циклу + + 50% Duty cycle 50% Робочого циклу + + 75% Duty cycle 75% Робочого циклу + Enable channel 2 Увімкнути канал 2 + Enable envelope 2 Увімкнути обвідну 2 + Enable envelope 2 loop Увімкнти повтор обвідної 2 + Enable sweep 2 Увімкнути розгортку 2 + Enable channel 3 Увімкнути канал 3 + Noise Frequency Частота шуму + Frequency sweep Частота темпу + Enable channel 4 Увімкнути канал 4 + Enable envelope 4 Увімкнути обвідну 4 + Enable envelope 4 loop Увімкнти повтор обвідної 4 + Quantize noise frequency when using note frequency Квантування частоту шуму при використанні частоти ноти + Use note frequency for noise Використовувати частоту ноти для шуму + Noise mode Форма шуму + Master Volume Основна гучність + Vibrato Вібрато @@ -5275,81 +6657,103 @@ PM (ФМ) режим означає Фазова Модуляція: Осцил OscillatorObject - Osc %1 volume - Гучність осциллятора %1 - - - Osc %1 panning - Стереобаланс для осциллятора %1 - - - Osc %1 coarse detuning - Підстроювання осциллятора %1 грубе - - - Osc %1 fine detuning left - Точне підстроювання лівого каналу осциллятора %1 - - - Osc %1 fine detuning right - Підстроювання правого каналу осциллятора %1 тонка - - - Osc %1 phase-offset - Зміщення фази осциллятора %1 - - - Osc %1 stereo phase-detuning - Підстроювання стерео-фази осциллятора %1 - - - Osc %1 wave shape - Гладкість сигналу осциллятора %1 - - - Modulation type %1 - Тип модуляції %1 - - + Osc %1 waveform Форма сигналу осциллятора %1 + Osc %1 harmonic Осц %1 гармонійний + + + + Osc %1 volume + Гучність осциллятора %1 + + + + + Osc %1 panning + Стереобаланс для осциллятора %1 + + + + + Osc %1 fine detuning left + Точне підстроювання лівого каналу осциллятора %1 + + + + Osc %1 coarse detuning + Підстроювання осциллятора %1 грубе + + + + Osc %1 fine detuning right + Підстроювання правого каналу осциллятора %1 тонка + + + + Osc %1 phase-offset + Зміщення фази осциллятора %1 + + + + Osc %1 stereo phase-detuning + Підстроювання стерео-фази осциллятора %1 + + + + Osc %1 wave shape + Гладкість сигналу осциллятора %1 + + + + Modulation type %1 + Тип модуляції %1 + PatchesDialog + Qsynth: Channel Preset Q-Синтезатор: Канал передустановлено + Bank selector Селектор банку + Bank Банк + Program selector Селектор програм + Patch Патч + Name І'мя + OK ОК + Cancel Скасувати @@ -5357,46 +6761,57 @@ PM (ФМ) режим означає Фазова Модуляція: Осцил PatmanView + Open other patch Відкрити інший патч + Click here to open another patch-file. Loop and Tune settings are not reset. Натисніть щоб відкрити інший патч-файл. Циклічність і налаштування при цьому збережуться. + Loop Повтор + Loop mode Режим повтору + Here you can toggle the Loop mode. If enabled, PatMan will use the loop information available in the file. Тут вмикається/вимикається режим повтору, при увімкнені PatMan буде використовувати інформацію про повтор з файлу. + Tune Підлаштувати + Tune mode Тип підстроювання + Here you can toggle the Tune mode. If enabled, PatMan will tune the sample to match the note's frequency. Тут вмикається/вимикається режим підстроювання. Якщо його увімкнено, то PatMan змінить запис так, щоб він збігався по частоті з нотою. + No file selected Файл не вибрано + Open patch file Відкрити патч-файл + Patch-Files (*.pat) Патч-файли (*.pat) @@ -5404,30 +6819,47 @@ PM (ФМ) режим означає Фазова Модуляція: Осцил PatternView + + use mouse wheel to set velocity of a step + використовуйте колесо миші для встановлення кроку гучності + + + + double-click to open in Piano Roll + Відкрити в редакторі нот подвійним клацанням миші + + + Open in piano-roll Відкрити в редакторі нот + Clear all notes Очистити всі ноти + Reset name Скинути назву + Change name Перейменувати + Add steps Додати такти + Remove steps Видалити такти + Clone Steps Клонувати такти @@ -5435,14 +6867,17 @@ PM (ФМ) режим означає Фазова Модуляція: Осцил PeakController + Peak Controller Контролер вершин + Peak Controller Bug Контролер вершин з багом + Due to a bug in older version of LMMS, the peak controllers may not be connect properly. Please ensure that peak controllers are connected properly and re-save this file. Sorry for any inconvenience caused. Через помилку в старій версії LMMS контролери вершин не можуть правильно підключатися. Будь-ласка переконайтеся, що контролери вершин правильно приєднані і перезбережіть цей файл, вибачте, за заподіяні незручності. @@ -5450,10 +6885,12 @@ PM (ФМ) режим означає Фазова Модуляція: Осцил PeakControllerDialog + PEAK ПІК + LFO Controller Контролер LFO @@ -5461,307 +6898,383 @@ PM (ФМ) режим означає Фазова Модуляція: Осцил PeakControllerEffectControlDialog + BASE БАЗА + Base amount: Базове значення: - Modulation amount: - Глибина модуляції: - - - Attack: - Вступ: - - - Release: - Зменшення: - - + AMNT ГЛИБ + + Modulation amount: + Глибина модуляції: + + + MULT МНОЖ + Amount Multiplicator: Величина множника: + ATCK ВСТУП + + Attack: + Вступ: + + + DCAY ЗГАС - Treshold: - Поріг: + + Release: + Зменшення: + TRSH - + TRSH + + + + Treshold: + Поріг: PeakControllerEffectControls + Base value Опорне значення + Modulation amount Глибина модуляції - Mute output - Заглушити вивід - - + Attack Вступ + Release Зменшення + + Treshold + Поріг + + + + Mute output + Заглушити вивід + + + Abs Value Абс Значення + Amount Multiplicator Величина множника - - Treshold - Поріг - PianoRoll - Please open a pattern by double-clicking on it! - Відкрийте шаблон за допомогою подвійного клацання мишею! - - - Last note - По останій ноті - - - Note lock - Фіксація нот - - + Note Velocity Гучність нот + Note Panning Стереофонія нот + Mark/unmark current semitone Відмітити/Зняти відмітку з поточного півтону - Mark current scale - Відмітити поточний підйом - - - Mark current chord - Відмітити поточний акорд - - - Unmark all - Зняти виділення - - - No scale - Без підйому - - - No chord - Прибрати акорди - - - Velocity: %1% - Гучність %1% - - - Panning: %1% left - Баланс %1% лівий - - - Panning: %1% right - Баланс %1% правий - - - Panning: center - Баланс: по середині - - - Please enter a new value between %1 and %2: - Введіть нове значення від %1 до %2: - - + Mark/unmark all corresponding octave semitones Відмітити/Зняти всі відповідні півтони октави + + Mark current scale + Відмітити поточний підйом + + + + Mark current chord + Відмітити поточний акорд + + + + Unmark all + Зняти виділення + + + Select all notes on this key Вибрати всі ноти на цій тональності + + + Note lock + Фіксація нот + + + + Last note + По останій ноті + + + + No scale + Без підйому + + + + No chord + Прибрати акорди + + + + Velocity: %1% + Гучність %1% + + + + Panning: %1% left + Баланс %1% лівий + + + + Panning: %1% right + Баланс %1% правий + + + + Panning: center + Баланс: по середині + + + + Please open a pattern by double-clicking on it! + Відкрийте шаблон за допомогою подвійного клацання мишею! + + + + + Please enter a new value between %1 and %2: + Введіть нове значення від %1 до %2: + PianoRollWindow + Play/pause current pattern (Space) Гра/Пауза поточної мелодії (Пробіл) + Record notes from MIDI-device/channel-piano Записати ноти з цифрового музичного інструмента (MIDI) + Record notes from MIDI-device/channel-piano while playing song or BB track Записати ноти з цифрового музичного інструменту (MIDI) під час відтворення пісні або доріжки Ритм-Басу + Stop playing of current pattern (Space) Зупинити програвання поточної мелодії (Пробіл) + Click here to play the current pattern. This is useful while editing it. The pattern is automatically looped when its end is reached. Натисніть тут щоб програти поточний шаблон. Це може стати в нагоді при його редагуванні. Після закінчення шаблону відтворення почнеться спочатку. + Click here to record notes from a MIDI-device or the virtual test-piano of the according channel-window to the current pattern. When recording all notes you play will be written to this pattern and you can play and edit them afterwards. Натисніть цю кнопку, якщо ви хочете записати ноти з пристрою MIDI або віртуального синтезатора відповідного каналу. Пізніше ви зможете відредагувати записаний шаблон. + Click here to record notes from a MIDI-device or the virtual test-piano of the according channel-window to the current pattern. When recording all notes you play will be written to this pattern and you will hear the song or BB track in the background. Натисніть цю кнопку, якщо ви хочете записати ноти з пристрою MIDI або віртуального синтезатора відповідного каналу. Під час запису всі ноти записуються в цей шаблон, і ви будете чути композицію або РБ доріжку на задньому плані. + Click here to stop playback of current pattern. Натисніть тут, якщо ви хочете зупинити відтворення поточного шаблону. + + Edit actions + Зміна + + + Draw mode (Shift+D) Режим малювання (Shift + D) + Erase mode (Shift+E) Режим стирання (Shift+E) + Select mode (Shift+S) Режим вибору нот (Shift+S) - Detune mode (Shift+T) - Режим підлаштовування (Shift+T) - - + Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold %1 to temporarily go into select mode. Режим малювання нот, в ньому ви можете додавати/переміщати і змінювати тривалість одиночних нот. Це режим за замовчуванням і використовується більшу частину часу. Для включення цього режиму можна скористатися комбінацією клавіш Shift+D, утримуйте %1 для тимчасового перемикання в режим вибору. + Click here and erase mode will be activated. In this mode you can erase notes. You can also press 'Shift+E' on your keyboard to activate this mode. Режим стирання. У цьому режимі ви можете стирати ноти. Для увімкнення цього режиму можна скористатися комбінацією клавіш Shift+E. + Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold %1 in draw mode to temporarily use select mode. Режим виділення. У цьому режимі можна виділяти ноти, також можна утримувати %1 в режимі малювання, щоб на час увійти в режим виділення. - Click here and detune mode will be activated. In this mode you can click a note to open its automation detuning. You can utilize this to slide notes from one to another. You can also press 'Shift+T' on your keyboard to activate this mode. - Режим підстроювання. У цьому режимі можна вибирати ноти для автоматизації їх підлаштування. Можна використовувати це для переходів нот від однієї до іншої. Для активації з клавіатури <Shift+T>. + + Pitch Bend mode (Shift+T) + Режим Pitch Bend (Shift+T) - Cut selected notes (%1+X) - Перемістити виділені ноти до буферу (%1+X) + + Click here and Pitch Bend mode will be activated. In this mode you can click a note to open its automation detuning. You can utilize this to slide notes from one to another. You can also press 'Shift+T' on your keyboard to activate this mode. + Натисніть тут для активації Pitch Blend режиму. Ви зможете клікнути на ноту, щоб почати автоматичний детюн. Можна використовувати це для "ковзання" від однієї ноти до іншої. Можна включити цей режим за допомогою Shift + T. - Copy selected notes (%1+C) - Копіювати виділені ноти до буферу (%1+X) - - - Paste notes from clipboard (%1+V) - Вставити ноти з буферу (%1+V) - - - Click here and the selected notes will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. - При натиснені цієї кнопки виділені ноти будуть вирізані до буферу. Пізніше ви зможете вставити їх в будь-яке місце будь-якого шаблону за допомогою кнопки "Вставити". - - - Click here and the selected notes will be copied into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. - При натиснені цієї кнопки виділені ноти буде скопійовано до буферу. Пізніше ви зможете вставити їх в будь-яке місце будь-якого шаблону за допомогою кнопки "Вставити". - - - Click here and the notes from the clipboard will be pasted at the first visible measure. - При натиснені цієї кнопки ноти з буферу будуть вставлені в перший видимий такт. - - - This controls the magnification of an axis. It can be helpful to choose magnification for a specific task. For ordinary editing, the magnification should be fitted to your smallest notes. - Цим контролюється масштаб осі. Це може бути корисно для спеціальних завдань. Для звичайного редагування, масштаб слід встановлювати за найменшою нотою. - - - The 'Q' stands for quantization, and controls the grid size notes and control points snap to. With smaller quantization values, you can draw shorter notes in Piano Roll, and more exact control points in the Automation Editor. - "Q" позначає квантування і контролює розмір нотної сітки і контрольні точки тяжіння. З меншою величиною квантування, можна малювати короткі ноти в редаторі нот і більш точно контролювати точки в редакторі Автоматизації. - - - This lets you select the length of new notes. 'Last Note' means that LMMS will use the note length of the note you last edited - Дозволяє вибрати довжину нової ноти. "Остання Нота" означає, що LMMS буде використовувати довжину ноти, зміненої в останній раз - - - The feature is directly connected to the context-menu on the virtual keyboard, to the left in Piano Roll. After you have chosen the scale you want in this drop-down menu, you can right click on a desired key in the virtual keyboard, and then choose 'Mark current Scale'. LMMS will highlight all notes that belongs to the chosen scale, and in the key you have selected! - Функція безпосередньо пов'язана з контекстним меню на віртуальній клавіатурі зліва в нотному редакторі. Після того, як обраний масштаб у випадаючому меню, можна натиснути правою кнопкою у віртуальній клавіатурі і вибрати "Mark Current Scale" (Відзначити поточний масштаб). LMMS підсвітить всі ноти які лежать в обраному масштабі для обраної клавіші! - - - Let you select a chord which LMMS then can draw or highlight.You can find the most common chords in this drop-down menu. After you have selected a chord, click anywhere to place the chord, and right click on the virtual keyboard to open context menu and highlight the chord. To return to single note placement, you need to choose 'No chord' in this drop-down menu. - Дозволяє вибрати акорд, який LMMS потім зможе намалювати або підсвітити. У цьому меню можна знайти найбільш популярні акорди. Після того, як ви вибрали акорд, натисніть в будь-якому місці, щоб поставити його, а правим кліком по віртуальній клавіатурі відкривається контекстне меню і підсвічування акорду. Для повернення в режим однієї ноти потрібно вибрати "Без акорду" в цьому випадаючому меню. - - - Edit actions - Зміна + + Quantize + Квантовать + Copy paste controls Управління копіюванням та вставкою + + Cut selected notes (%1+X) + Перемістити виділені ноти до буферу (%1+X) + + + + Copy selected notes (%1+C) + Копіювати виділені ноти до буферу (%1+X) + + + + Paste notes from clipboard (%1+V) + Вставити ноти з буферу (%1+V) + + + + Click here and the selected notes will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. + При натиснені цієї кнопки виділені ноти будуть вирізані до буферу. Пізніше ви зможете вставити їх в будь-яке місце будь-якого шаблону за допомогою кнопки "Вставити". + + + + Click here and the selected notes will be copied into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. + При натиснені цієї кнопки виділені ноти буде скопійовано до буферу. Пізніше ви зможете вставити їх в будь-яке місце будь-якого шаблону за допомогою кнопки "Вставити". + + + + Click here and the notes from the clipboard will be pasted at the first visible measure. + При натиснені цієї кнопки ноти з буферу будуть вставлені в перший видимий такт. + + + Timeline controls Управління хронологією + Zoom and note controls Управління масштабом і нотами + + This controls the magnification of an axis. It can be helpful to choose magnification for a specific task. For ordinary editing, the magnification should be fitted to your smallest notes. + Цим контролюється масштаб осі. Це може бути корисно для спеціальних завдань. Для звичайного редагування, масштаб слід встановлювати за найменшою нотою. + + + + The 'Q' stands for quantization, and controls the grid size notes and control points snap to. With smaller quantization values, you can draw shorter notes in Piano Roll, and more exact control points in the Automation Editor. + "Q" позначає квантування і контролює розмір нотної сітки і контрольні точки тяжіння. З меншою величиною квантування, можна малювати короткі ноти в редаторі нот і більш точно контролювати точки в редакторі Автоматизації. + + + + This lets you select the length of new notes. 'Last Note' means that LMMS will use the note length of the note you last edited + Дозволяє вибрати довжину нової ноти. "Остання Нота" означає, що LMMS буде використовувати довжину ноти, зміненої в останній раз + + + + The feature is directly connected to the context-menu on the virtual keyboard, to the left in Piano Roll. After you have chosen the scale you want in this drop-down menu, you can right click on a desired key in the virtual keyboard, and then choose 'Mark current Scale'. LMMS will highlight all notes that belongs to the chosen scale, and in the key you have selected! + Функція безпосередньо пов'язана з контекстним меню на віртуальній клавіатурі зліва в нотному редакторі. Після того, як обраний масштаб у випадаючому меню, можна натиснути правою кнопкою у віртуальній клавіатурі і вибрати "Mark Current Scale" (Відзначити поточний масштаб). LMMS підсвітить всі ноти які лежать в обраному масштабі для обраної клавіші! + + + + Let you select a chord which LMMS then can draw or highlight.You can find the most common chords in this drop-down menu. After you have selected a chord, click anywhere to place the chord, and right click on the virtual keyboard to open context menu and highlight the chord. To return to single note placement, you need to choose 'No chord' in this drop-down menu. + Дозволяє вибрати акорд, який LMMS потім зможе намалювати або підсвітити. У цьому меню можна знайти найбільш популярні акорди. Після того, як ви вибрали акорд, натисніть в будь-якому місці, щоб поставити його, а правим кліком по віртуальній клавіатурі відкривається контекстне меню і підсвічування акорду. Для повернення в режим однієї ноти потрібно вибрати "Без акорду" в цьому випадаючому меню. + + + + Piano-Roll - %1 Нотний редактор - %1 + + Piano-Roll - no pattern Нотний редактор - без шаблону - - Quantize - Квантовать - PianoView + Base note Опорна нота @@ -5769,20 +7282,24 @@ PM (ФМ) режим означає Фазова Модуляція: Осцил Plugin + Plugin not found Модуль не знайдено + The plugin "%1" wasn't found or could not be loaded! Reason: "%2" Модуль «%1» відсутній чи не може бути завантажений! Причина: «%2» + Error while loading plugin Помилка завантаження модуля + Failed to load plugin "%1"! Не вдалося завантажити модуль «%1»! @@ -5790,25 +7307,30 @@ Reason: "%2" PluginBrowser + + Instrument Plugins + Модулі інструментів + + + Instrument browser Огляд інструментів + Drag an instrument into either the Song-Editor, the Beat+Bassline Editor or into an existing instrument track. Ви можете переносити потрібні вам інструменти з цієї панелі в музичний, ритм-бас редактор або в існуючу доріжку інструменту. - - Instrument Plugins - - PluginFactory + Plugin not found. Модуль не знайдено. + LMMS plugin %1 does not have a plugin descriptor named %2! LMMS плагін %1 не має опису плагіна з ім'ям %2! @@ -5816,129 +7338,160 @@ Reason: "%2" ProjectNotes - Edit Actions - Зміна - - - &Undo - &U Скасувати - - - %1+Z - %1+Z - - - &Redo - &R Повторити - - - %1+Y - %1+Y - - - &Copy - &C Копіювати - - - %1+C - %1+C - - - Cu&t - &t Вирізати - - - %1+X - %1+X - - - &Paste - &P Вставити - - - %1+V - %1+V - - - Format Actions - Форматування - - - &Bold - Напів&жирний - - - %1+B - %1+B - - - &Italic - &Курсив - - - %1+I - %1+I - - - &Underline - &Підкреслити - - - %1+U - %1+U - - - &Left - По &лівому краю - - - %1+L - %1+L - - - C&enter - По &центрі - - - %1+E - %1+E - - - &Right - По &правому краю - - - %1+R - %1+R - - - &Justify - По &ширині - - - %1+J - %1+J - - - &Color... - &C Колір... - - + Project Notes Примітки проекту + Enter project notes here - + Напишіть примітки до проекту тут + + + + Edit Actions + Зміна + + + + &Undo + &U Скасувати + + + + %1+Z + %1+Z + + + + &Redo + &R Повторити + + + + %1+Y + %1+Y + + + + &Copy + &C Копіювати + + + + %1+C + %1+C + + + + Cu&t + &t Вирізати + + + + %1+X + %1+X + + + + &Paste + &P Вставити + + + + %1+V + %1+V + + + + Format Actions + Форматування + + + + &Bold + Напів&жирний + + + + %1+B + %1+B + + + + &Italic + &Курсив + + + + %1+I + %1+I + + + + &Underline + &Підкреслити + + + + %1+U + %1+U + + + + &Left + По &лівому краю + + + + %1+L + %1+L + + + + C&enter + По &центрі + + + + %1+E + %1+E + + + + &Right + По &правому краю + + + + %1+R + %1+R + + + + &Justify + По &ширині + + + + %1+J + %1+J + + + + &Color... + &C Колір... ProjectRenderer + WAV-File (*.wav) Файл WAV (*.wav) + Compressed OGG-File (*.ogg) Стиснутий файл OGG (*.ogg) @@ -5947,64 +7500,97 @@ Reason: "%2" + Compressed MP3-File (*.mp3) - + Стиснутий MP3-файл (* .mp3) QWidget + + + Name: І'мя: + + Maker: Розробник: + + Copyright: Авторське право: + + Requires Real Time: Потрібна обробка в реальному часі: + + + + + + Yes Так + + + + + + No Ні + + Real Time Capable: Робота в реальному часі: + + In Place Broken: Замість зламаного: + + Channels In: Канали в: + + Channels Out: Канали з: - File: - Файл: - - + File: %1 Файл: %1 + + + File: + Файл: + RenameDialog + Rename... Перейменувати ... @@ -6012,34 +7598,42 @@ Reason: "%2" ReverbSCControlDialog + Input Ввід + Input Gain: Вхідне підсилення: + Size - + Розмір + Size: - + Розмір: + Color - + Колір + Color: - + Колір: + Output Вивід + Output Gain: Вихідне підсилення: @@ -6047,100 +7641,123 @@ Reason: "%2" ReverbSCControls + Input Gain - + Вхідне підсилення + Size - + Розмір + Color - + Колір + Output Gain - + Вихідне підсилення SampleBuffer + + Fail to open file + Не вдається відкрити файл + + + + Audio files are limited to %1 MB in size and %2 minutes of playing time + Аудіофайли обмежено розміром в %1 МБ і %2 хвилин(и) програвання + + + Open audio file Відкрити звуковий файл - Wave-Files (*.wav) - Файли Wave (*.wav) - - - OGG-Files (*.ogg) - Файли OGG (*.ogg) - - - DrumSynth-Files (*.ds) - Файли DrumSynth (*.ds) - - - FLAC-Files (*.flac) - Файли FLAC (*.flac) - - - SPEEX-Files (*.spx) - Файли SPEEX (*.spx) - - - VOC-Files (*.voc) - Файли VOC (*.voc) - - - AIFF-Files (*.aif *.aiff) - Файли AIFF (*.aif *.aiff) - - - AU-Files (*.au) - Файли AU (*.au) - - - RAW-Files (*.raw) - Файли RAW (*.raw) - - + All Audio-Files (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw) Всі Аудіо-файли (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw) - Fail to open file - + + Wave-Files (*.wav) + Файли Wave (*.wav) - Audio files are limited to %1 MB in size and %2 minutes of playing time - + + OGG-Files (*.ogg) + Файли OGG (*.ogg) + + + + DrumSynth-Files (*.ds) + Файли DrumSynth (*.ds) + + + + FLAC-Files (*.flac) + Файли FLAC (*.flac) + + + + SPEEX-Files (*.spx) + Файли SPEEX (*.spx) + + + + VOC-Files (*.voc) + Файли VOC (*.voc) + + + + AIFF-Files (*.aif *.aiff) + Файли AIFF (*.aif *.aiff) + + + + AU-Files (*.au) + Файли AU (*.au) + + + + RAW-Files (*.raw) + Файли RAW (*.raw) SampleTCOView + double-click to select sample Виберіть запис подвійним натисненням миші + Delete (middle mousebutton) Видалити (середня кнопка мишки) + Cut Вирізати + Copy Копіювати + Paste Вставити + Mute/unmute (<%1> + middle click) Заглушити/включити (<%1> + середня кнопка миші) @@ -6148,41 +7765,51 @@ Reason: "%2" SampleTrack - Sample track - Доріжка запису - - + Volume Гучність + Panning Баланс + + + + Sample track + Доріжка запису + SampleTrackView + Track volume Гучність доріжки + Channel volume: Гучність каналу: + VOL ГУЧН + Panning Баланс + Panning: Баланс: + PAN БАЛ @@ -6190,496 +7817,659 @@ Reason: "%2" SetupDialog + Setup LMMS Налаштування LMMS + + General settings Загальні налаштування + BUFFER SIZE РОЗМІР БУФЕРУ + + Reset to default-value Відновити значення за замовчуванням + MISC РІЗНЕ + Enable tooltips Включити підказки + Show restart warning after changing settings Показувати попередження про перезапуск при зміні налаштувань + + Display volume as dBFS + Відображати гучність в децибелах + + + Compress project files per default За замовчуванням стискати файли проектів + One instrument track window mode Режим вікна однієї інструментальної доріжки + HQ-mode for output audio-device Режим високої якості для виведення звуку + Compact track buttons Стиснути кнопки доріжки + Sync VST plugins to host playback Синхронізувати VST плагіни з хостом відтворення + Enable note labels in piano roll Включити позначення нот у музичному редакторі + Enable waveform display by default Включити відображення форми хвилі за замовчуванням + Keep effects running even without input Продовжувати роботу ефектів навіть без вхідного сигналу + Create backup file when saving a project Створю запасний файл при збереженні проекту + + Reopen last project on start + Відкривати останній проект при запуску + + + + Use built-in NaN handler + Використовувати вбудований обробник NaN + + + + PLUGIN EMBEDDING + ВСТАНОВИТИ УПРАВЛІННЯ + + + + No embedding + Не встановлено + + + + Embed using Qt API + Встановлення використовуючи Qt API + + + + Embed using native Win32 API + Встановлення використовуючи рідний Win32 API + + + + Embed using XEmbed protocol + Встановлення використовуючи протокол XEmbed + + + LANGUAGE МОВА + + Paths Шляхи + + Directories + Каталоги + + + LMMS working directory Робочий каталог LMMS - VST-plugin directory - Каталог модулів VST + + Themes directory + Каталог тем + Background artwork Фонове зображення + + VST-plugin directory + Каталог модулів VST + + + + GIG directory + Каталог GIG + + + + SF2 directory + Каталог SF2 + + + + LADSPA plugin directories + Каталог модулів LADSPA + + + STK rawwave directory Каталог STK rawwave + Default Soundfont File Основний Soundfont файл + + Performance settings Налаштування продуктивності + + Auto save + Авто-збереження + + + + Enable auto-save + Увімкнути автоматичне збереження + + + + Allow auto-save while playing + Дозволити автоматичне збереження під час відтворення + + + UI effects vs. performance Візуальні ефекти / продуктивність + Smooth scroll in Song Editor Плавне прокручування в музичному редакторі + Show playback cursor in AudioFileProcessor Показувати покажчик відтворення в процесорі аудіо файлів + + Audio settings Параметри звуку + AUDIO INTERFACE ЗВУКОВА СИСТЕМА + + MIDI settings Параметри MIDI + MIDI INTERFACE ІНТЕРФЕЙС MIDI + OK ОК + Cancel Скасувати + Restart LMMS Перезапустіть LMMS + Please note that most changes won't take effect until you restart LMMS! Врахуйте, що більшість налаштувань не вступлять в силу до перезапуску програми! + Frames: %1 Latency: %2 ms Фрагментів: %1 Затримка: %2 мс + Here you can setup the internal buffer-size used by LMMS. Smaller values result in a lower latency but also may cause unusable sound or bad performance, especially on older computers or systems with a non-realtime kernel. Тут ви можете налаштувати розмір внутрішнього звукового буфера LMMS. Менші значення дають менший час відгуку програми, але підвищують споживання ресурсів - це особливо помітно на старих машинах і системах, ядро ​​яких не підтримує пріоритету реального часу. Якщо спостерігається переривчастий звук, спробуйте збільшити розмір буферу. + Choose LMMS working directory Вибір робочого каталогу LMMS - Choose your VST-plugin directory - Вибір свого каталогу для модулів VST - - - Choose artwork-theme directory - Вибір каталогу з темою оформлення для LMMS - - - Choose LADSPA plugin directory - Вибір каталогу з модулями LADSPA - - - Choose STK rawwave directory - Вибір каталогу STK rawwave - - - Choose default SoundFont - Вибрати головний SoundFont - - - Choose background artwork - Вибрати фонове зображення - - - Here you can select your preferred audio-interface. Depending on the configuration of your system during compilation time you can choose between ALSA, JACK, OSS and more. Below you see a box which offers controls to setup the selected audio-interface. - Будь ласка, виберіть звукову систему. Залежно від конфігурації під час компілювання програми, ви можете використовувати ALSA, JACK, OSS та інші. У нижній частині вікна налаштування можна задати специфічні параметри обраної системи. - - - Here you can select your preferred MIDI-interface. Depending on the configuration of your system during compilation time you can choose between ALSA, OSS and more. Below you see a box which offers controls to setup the selected MIDI-interface. - Будь ласка, виберіть інтерфейс MIDI. Залежно від конфігурації під час компілювання програми, ви можете використовувати ALSA, OSS та інші. У нижній частині вікна налаштування можна задати специфічні параметри обраного інтерфейсу. - - - Reopen last project on start - Відкривати останній проект при запуску - - - Directories - Каталоги - - - Themes directory - Каталог тем - - - GIG directory - Каталог GIG - - - SF2 directory - Каталог SF2 - - - LADSPA plugin directories - Каталог модулів LADSPA - - - Auto save - Авто-збереження - - + Choose your GIG directory Виберіть каталог GIG + Choose your SF2 directory Виберіть каталог SF2 + + Choose your VST-plugin directory + Вибір свого каталогу для модулів VST + + + + Choose artwork-theme directory + Вибір каталогу з темою оформлення для LMMS + + + + Choose LADSPA plugin directory + Вибір каталогу з модулями LADSPA + + + + Choose STK rawwave directory + Вибір каталогу STK rawwave + + + + Choose default SoundFont + Вибрати головний SoundFont + + + + Choose background artwork + Вибрати фонове зображення + + + minutes хвилин + minute хвилина - Display volume as dBFS - Відображати гучність в децибелах - - - Enable auto-save - - - - Allow auto-save while playing - - - + Disabled - + Вимкнено + Auto-save interval: %1 - + Інтервал автоматичного збереження: %1 + Set the time between automatic backup to %1. Remember to also save your project manually. You can choose to disable saving while playing, something some older systems find difficult. - + Встановіть проміжок часу автоматичного резервного копіювання в %1. +Не забудьте також зберегти проект вручну. Ви можете вимкнути автозбереження, інколи деяким старим системи тяжко в таком режимі. + + + + Here you can select your preferred audio-interface. Depending on the configuration of your system during compilation time you can choose between ALSA, JACK, OSS and more. Below you see a box which offers controls to setup the selected audio-interface. + Будь ласка, виберіть звукову систему. Залежно від конфігурації під час компілювання програми, ви можете використовувати ALSA, JACK, OSS та інші. У нижній частині вікна налаштування можна задати специфічні параметри обраної системи. + + + + Here you can select your preferred MIDI-interface. Depending on the configuration of your system during compilation time you can choose between ALSA, OSS and more. Below you see a box which offers controls to setup the selected MIDI-interface. + Будь ласка, виберіть інтерфейс MIDI. Залежно від конфігурації під час компілювання програми, ви можете використовувати ALSA, OSS та інші. У нижній частині вікна налаштування можна задати специфічні параметри обраного інтерфейсу. Song + Tempo Темп + Master volume Основна гучність + Master pitch Основна тональність - Project saved - Проект збережено - - - The project %1 is now saved. - Проект %1 збережено. - - - Project NOT saved. - Проект НЕ ЗБЕРЕЖЕНО. - - - The project %1 was not saved! - Проект %1 не збережено! - - - Import file - Імпорт файлу - - - MIDI sequences - MiDi послідовність - - - Hydrogen projects - Hydrogen проекти - - - All file types - Всі типи файлів - - - Empty project - Проект порожній - - - This project is empty so exporting makes no sense. Please put some items into Song Editor first! - Проект нічого не містить, так що й експортувати нічого. Спочатку додайте хоча б одну доріжку за допомогою музичного редактора! - - - Select directory for writing exported tracks... - Виберіть теку для запису експортованих доріжок ... - - - untitled - Без назви - - - Select file for project-export... - Вибір файлу для експорту проекту ... - - - The following errors occured while loading: - Наступні помилки виникли при завантаженні: - - - MIDI File (*.mid) - MIDI-файл (* mid) - - + LMMS Error report Повідомлення про помилку в LMMS + + Project saved + Проект збережено + + + + The project %1 is now saved. + Проект %1 збережено. + + + + Project NOT saved. + Проект НЕ ЗБЕРЕЖЕНО. + + + + The project %1 was not saved! + Проект %1 не збережено! + + + + Import file + Імпорт файлу + + + + MIDI sequences + MiDi послідовність + + + + Hydrogen projects + Hydrogen проекти + + + + All file types + Всі типи файлів + + + + + Empty project + Проект порожній + + + + + This project is empty so exporting makes no sense. Please put some items into Song Editor first! + Проект нічого не містить, так що й експортувати нічого. Спочатку додайте хоча б одну доріжку за допомогою музичного редактора! + + + + Select directory for writing exported tracks... + Виберіть теку для запису експортованих доріжок ... + + + + + untitled + Без назви + + + + + Select file for project-export... + Вибір файлу для експорту проекту ... + + + Save project - + Зберегти проект + + + + MIDI File (*.mid) + MIDI-файл (* mid) + + + + The following errors occured while loading: + Наступні помилки виникли при завантаженні: SongEditor + Could not open file Не можу відкрити файл - Could not write file - Не можу записати файл - - + Could not open file %1. You probably have no permissions to read this file. Please make sure to have at least read permissions to the file and try again. Неможливо відкрити файл %1, ймовірно, немає дозволу на його читання. Будь-ласка переконайтеся, що є принаймні права на читання цього файлу і спробуйте ще раз. - Error in file - Помилка у файлі - - - The file %1 seems to contain errors and therefore can't be loaded. - Файл %1 можливо містить помилки через які не може завантажитися. - - - Tempo - Темп - - - TEMPO/BPM - ТЕМП/BPM - - - tempo of song - Темп музики - - - The tempo of a song is specified in beats per minute (BPM). If you want to change the tempo of your song, change this value. Every measure has four beats, so the tempo in BPM specifies, how many measures / 4 should be played within a minute (or how many measures should be played within four minutes). - Це значення задає темп музики в ударах в хвилину (англ. аббр. BPM). На кожен такт приходить чотири удари, так що темп в ударах в хвилину фактично вказує, скільки чвертей такту програється за хвилину (або, що те ж, кількість тактів, що програються за чотири хвилини). - - - High quality mode - Висока якість - - - Master volume - Основна гучність - - - master volume - основна гучність - - - Master pitch - Основна тональність - - - master pitch - основна тональність - - - Value: %1% - Значення: %1% - - - Value: %1 semitones - Значення: %1 півтон(у/ів) + + Could not write file + Не можу записати файл + Could not open %1 for writing. You probably are not permitted to write to this file. Please make sure you have write-access to the file and try again. Неможливо відкрити %1 для запису, можливо, немає дозволу на запис в цей файл, будь-ласка упевніться, що є доступ до цього файлу і спробуйте знову. + + Error in file + Помилка у файлі + + + + The file %1 seems to contain errors and therefore can't be loaded. + Файл %1 можливо містить помилки через які не може завантажитися. + + + + Version difference + Різниця версій + + + + This %1 was created with LMMS %2. + Цей %1 було створено в LMMS версії %2 + + + template шаблон + project проект - Version difference - + + Tempo + Темп - This %1 was created with LMMS %2. - Цей %1 було створено в LMMS версії %2 + + TEMPO/BPM + ТЕМП/BPM + + + + tempo of song + Темп музики + + + + The tempo of a song is specified in beats per minute (BPM). If you want to change the tempo of your song, change this value. Every measure has four beats, so the tempo in BPM specifies, how many measures / 4 should be played within a minute (or how many measures should be played within four minutes). + Це значення задає темп музики в ударах в хвилину (англ. аббр. BPM). На кожен такт приходить чотири удари, так що темп в ударах в хвилину фактично вказує, скільки чвертей такту програється за хвилину (або, що те ж, кількість тактів, що програються за чотири хвилини). + + + + High quality mode + Висока якість + + + + + Master volume + Основна гучність + + + + master volume + основна гучність + + + + + Master pitch + Основна тональність + + + + master pitch + основна тональність + + + + Value: %1% + Значення: %1% + + + + Value: %1 semitones + Значення: %1 півтон(у/ів) SongEditorWindow + Song-Editor Музичний редактор + Play song (Space) Почати відтворення (Пробіл) + Record samples from Audio-device Записати семпл зі звукового пристрою + Record samples from Audio-device while playing song or BB track Записати семпл з аудіо-пристрої під час відтворення в музичному чи ритм/бас редакторі + Stop song (Space) Зупинити відтворення (Пробіл) - Add beat/bassline - Додати ритм/бас - - - Add sample-track - Додати доріжку запису - - - Add automation-track - Додати доріжку автоматизації - - - Draw mode - Режим малювання - - - Edit mode (select and move) - Правка (виділення/переміщення) - - + Click here, if you want to play your whole song. Playing will be started at the song-position-marker (green). You can also move it while playing. Натисніть, щоб прослухати створену мелодію. Відтворення почнеться з позиції курсора (зелений трикутник); ви можете рухати його під час програвання. + Click here, if you want to stop playing of your song. The song-position-marker will be set to the start of your song. Натисніть сюди, якщо хочете зупинити відтворення мелодії. Курсор при цьому буде встановлений на початок композиції. + Track actions Стежити + + Add beat/bassline + Додати ритм/бас + + + + Add sample-track + Додати доріжку запису + + + + Add automation-track + Додати доріжку автоматизації + + + Edit actions Зміна + + Draw mode + Режим малювання + + + + Edit mode (select and move) + Правка (виділення/переміщення) + + + Timeline controls Управління хронологією + Zoom controls Управління масштабом @@ -6687,10 +8477,12 @@ Remember to also save your project manually. You can choose to disable saving wh SpectrumAnalyzerControlDialog + Linear spectrum Лінійний спектр + Linear Y axis Лінійна вісь ординат @@ -6698,14 +8490,17 @@ Remember to also save your project manually. You can choose to disable saving wh SpectrumAnalyzerControls + Linear spectrum Лінійний спектр + Linear Y axis Лінійна вісь ординат + Channel mode Режим каналу @@ -6713,14 +8508,17 @@ Remember to also save your project manually. You can choose to disable saving wh SubWindow + Close Закрити + Maximize Розгорнути + Restore Відновити @@ -6728,6 +8526,8 @@ Remember to also save your project manually. You can choose to disable saving wh TabWidget + + Settings for %1 Налаштування для %1 @@ -6735,74 +8535,93 @@ Remember to also save your project manually. You can choose to disable saving wh TempoSyncKnob + + Tempo Sync Синхронізація темпу + No Sync Синхронізації немає + Eight beats Вісім ударів (дві ноти) + Whole note Ціла нота + Half note Півнота + Quarter note Чверть ноти + 8th note Восьма ноти + 16th note 1/16 ноти + 32nd note 1/32 ноти + Custom... Своя... + Custom Своя + Synced to Eight Beats Синхро по 8 ударам + Synced to Whole Note Синхро по цілій ноті + Synced to Half Note Синхро по половині ноти + Synced to Quarter Note Синхро по чверті ноти + Synced to 8th Note Синхро по 1/8 ноти + Synced to 16th Note Синхро по 1/16 ноти + Synced to 32nd Note Синхро по 1/32 ноти @@ -6810,30 +8629,37 @@ Remember to also save your project manually. You can choose to disable saving wh TimeDisplayWidget + click to change time units натисніть для зміни одиниць часу + MIN ХВ + SEC С + MSEC МС + BAR БАР + BEAT БІТ + TICK ТІК @@ -6841,34 +8667,43 @@ Remember to also save your project manually. You can choose to disable saving wh TimeLineWidget + Enable/disable auto-scrolling Увімк/вимк автопрокрутку + Enable/disable loop-points Увімк/вимк точки петлі + After stopping go back to begin Після зупинки переходити до початку + After stopping go back to position at which playing was started Після зупинки переходити до місця, з якого почалося відтворення + After stopping keep position Залишатися на місці зупинки + + Hint Підказка + Press <%1> to disable magnetic loop points. Натисніть <%1>, щоб прибрати прилипання точок циклу. + Hold <Shift> to move the begin loop point; Press <%1> to disable magnetic loop points. Зажміть <Shift> щоб змістити початок точок циклу; Натисніть <%1>, щоб прибрати прилипання точок циклу. @@ -6876,10 +8711,12 @@ Remember to also save your project manually. You can choose to disable saving wh Track + Mute Тиша + Solo Соло @@ -6887,49 +8724,71 @@ Remember to also save your project manually. You can choose to disable saving wh TrackContainer + Couldn't import file Не можу імпортувати файл + Couldn't find a filter for importing file %1. You should convert this file into a format supported by LMMS using another software. Не можу знайти фільтр для імпорту файла %1. Для підключення цього файлу перетворіть його в формат, підтримуваний LMMS. + Couldn't open file Не можу відкрити файл + Couldn't open file %1 for reading. Please make sure you have read-permission to the file and the directory containing the file and try again! Не можу відкрити файл %1 для запису. Перевірте, чи володієте ви правами на запис в обраний файл і каталог що його містить і спробуйте знову! + Loading project... Завантаження проекту ... + + Cancel Скасувати + + Please wait... Зачекайте будь-ласка ... - Importing MIDI-file... - Імпортую файл MIDI... + + Loading cancelled + Завантаження скасовано + + Project loading was cancelled. + Завантаження проекту скасовано. + + + Loading Track %1 (%2/Total %3) - + Завантаження треку %1 (%2/з %3) + + + + Importing MIDI-file... + Імпортую файл MIDI... TrackContentObject + Mute Тиша @@ -6937,46 +8796,59 @@ Please make sure you have read-permission to the file and the directory containi TrackContentObjectView + Current position Позиція + + Hint Підказка + Press <%1> and drag to make a copy. Натисніть <%1> і перетягніть, щоб створити копію. + Current length Тривалість + Press <%1> for free resizing. Для вільної зміни розміру натисніть <%1>. + + %1:%2 (%3:%4 to %5:%6) %1:%2 (від %3:%4 до %5:%6) + Delete (middle mousebutton) Видалити (середня кнопка мишки) + Cut Вирізати + Copy Копіювати + Paste Вставити + Mute/unmute (<%1> + middle click) Заглушити/включити (<%1> + середня кнопка миші) @@ -6984,193 +8856,243 @@ Please make sure you have read-permission to the file and the directory containi TrackOperationsWidget + Press <%1> while clicking on move-grip to begin a new drag'n'drop-action. Затисніть <%1> і натискайте мишку під час руху, щоб почати нову перезбірку. + Actions for this track Дії для цієї доріжки + Mute Тиша + + Solo Соло + Mute this track Відключити доріжку + Clone this track Клонувати доріжку + Remove this track Видалити доріжку + Clear this track Очистити цю доріжку + FX %1: %2 ЕФ %1: %2 + + Assign to new FX Channel + Призначити до нового каналу ефекту + + + Turn all recording on Включити все на запис + Turn all recording off Вимкнути всі записи - - Assign to new FX Channel - Призначити до нового каналу ефекту - TripleOscillatorView + Use phase modulation for modulating oscillator 1 with oscillator 2 Модулювати фазу осциллятора 2 сигналом з 1 + Use amplitude modulation for modulating oscillator 1 with oscillator 2 Модулювати амплітуду осциллятора 2 сигналом з 1 + Mix output of oscillator 1 & 2 Змішати виходи 1 і 2 осцилляторів + Synchronize oscillator 1 with oscillator 2 Синхронізувати 1 осциллятор по 2 + Use frequency modulation for modulating oscillator 1 with oscillator 2 Модулювати частоту осциллятора 2 сигналом з 1 + Use phase modulation for modulating oscillator 2 with oscillator 3 Модулювати фазу осциллятора 3 сигналом з 2 + Use amplitude modulation for modulating oscillator 2 with oscillator 3 Модулювати амплітуду осциллятора 3 сигналом з 2 + Mix output of oscillator 2 & 3 Поєднати виходи осцилляторів 2 і 3 + Synchronize oscillator 2 with oscillator 3 Синхронізувати осциллятор 2 і 3 + Use frequency modulation for modulating oscillator 2 with oscillator 3 Модулювати частоту осциллятора 3 сигналом з 2 + Osc %1 volume: Гучність осциллятора %1: + With this knob you can set the volume of oscillator %1. When setting a value of 0 the oscillator is turned off. Otherwise you can hear the oscillator as loud as you set it here. Ця ручка встановлює гучність осциллятора %1. Якщо 0, то осциллятор вимикається, інакше буде чутно настільки голосно, настільки тут встановлено. + Osc %1 panning: Баланс для осциллятора %1: + With this knob you can set the panning of the oscillator %1. A value of -100 means 100% left and a value of 100 moves oscillator-output right. Регулятор стереобалансу осциллятора %1. Величина -100 позначає, що 100% сигналу йде в лівий канал, а 100 - в правий. + Osc %1 coarse detuning: Грубе підстроювання осциллятора %1: + semitones півтон(а,ів) + With this knob you can set the coarse detuning of oscillator %1. You can detune the oscillator 24 semitones (2 octaves) up and down. This is useful for creating sounds with a chord. Ця ручка встановлює грубе підстроювання осцилятора %1. Ви можете пістроїти осцилятор на 24 півтони (2 октави) вгору і вниз. Це корисно для створення звуків з акорду. + Osc %1 fine detuning left: Точне підстроювання лівого каналу осциллятора %1: + + cents Відсотки + With this knob you can set the fine detuning of oscillator %1 for the left channel. The fine-detuning is ranged between -100 cents and +100 cents. This is useful for creating "fat" sounds. Ця ручка встановлює точне підстроювання для лівого каналу осциллятора %1. Підстроювання задається в діапазоні від -100 сотих до +100 сотих. Це корисно для створення "насичених" звуків. + Osc %1 fine detuning right: Точна підстройка правого канала осциллятора %1: + With this knob you can set the fine detuning of oscillator %1 for the right channel. The fine-detuning is ranged between -100 cents and +100 cents. This is useful for creating "fat" sounds. Ця ручка встановлює точне підстроювання для правого каналу осциллятора %1. Підстроювання задається в діапазоні від -100 сотих до +100 сотих. Це корисно для створення "насичених" звуків. + Osc %1 phase-offset: Зміщення фази осциллятора %1: + + degrees градуси + With this knob you can set the phase-offset of oscillator %1. That means you can move the point within an oscillation where the oscillator begins to oscillate. For example if you have a sine-wave and have a phase-offset of 180 degrees the wave will first go down. It's the same with a square-wave. Ця ручка встановлює початкову фазу осциллятора %1, т. б. точку, з якої осциллятор починає виробляти сигнал. Наприклад, якщо ви задали синусоїдальну форму сигналу і початкову фазу 180º, хвиля спочатку піде вниз, а не вгору. Те ж саме для сигналу прямокутної форми. + Osc %1 stereo phase-detuning: Підстроювання стерео фази осциллятора %1: + With this knob you can set the stereo phase-detuning of oscillator %1. The stereo phase-detuning specifies the size of the difference between the phase-offset of left and right channel. This is very good for creating wide stereo sounds. Ця ручка встановлює фазове підстроювання осциллятора %1 між каналами, тобто різницю фаз між лівим і правим каналами. Це зручно для створення розширення стереоефектів. + Use a sine-wave for current oscillator. - Використовувати гармонійний (синусоїдальний) сигнал для цього осциллятора. + Генерувати гармонійний (синусоїдальний) сигнал. + Use a triangle-wave for current oscillator. - Використовувати трикутний сигнал для цього осциллятора. + Генерувати трикутний сигнал. + Use a saw-wave for current oscillator. - Використовувати зигзагоподібний сигнал для цього осциллятора. + Генерувати зигзагоподібний сигнал. + Use a square-wave for current oscillator. - Використовувати квадратний сигнал для цього осциллятора. + Генерувати квадрат. + Use a moog-like saw-wave for current oscillator. Використовувати муг-зигзаг для цього осциллятора. + Use an exponential wave for current oscillator. Використовувати експонентний сигнал для цього осциллятора. + Use white-noise for current oscillator. - Використовувати білий шум для цього осциллятора. + Генерувати білий шум. + Use a user-defined waveform for current oscillator. Задати форму сигналу. @@ -7178,105 +9100,131 @@ Please make sure you have read-permission to the file and the directory containi VersionedSaveDialog + Increment version number Збільшуючийся номер версії + Decrement version number Зменшуючийся номер версії + already exists. Do you want to replace it? - + вже існує. Замінити його? VestigeInstrumentView + Open other VST-plugin Відкрити інший VST плагін + Click here, if you want to open another VST-plugin. After clicking on this button, a file-open-dialog appears and you can select your file. Відкрити інший модуль VST. Після натискання на кнопку з'явиться стандартний діалог вибору файлу, де ви зможете вибрати потрібний модуль. - Show/hide GUI - Показати / приховати інтерфейс - - - Click here to show or hide the graphical user interface (GUI) of your VST-plugin. - Приховує / показує графічний користувальницький інтерфейс (GUI) обраного модуля VST. - - - Turn off all notes - Вимкнути всі ноти - - - Open VST-plugin - Відкрити модуль VST - - - DLL-files (*.dll) - Бібліотеки DLL (*.dll) - - - EXE-files (*.exe) - Програми EXE (*.exe) - - - No VST-plugin loaded - Модуль VST не завантажений - - + Control VST-plugin from LMMS host - Управління VST плагіном через LMMS + Управління VST плагіном через LMMS хост + Click here, if you want to control VST-plugin from host. - Натисніть тут для контролю VST плагіна через хост. + Натисніть тут, для контролю VST плагіном через хост. + Open VST-plugin preset - Відкрити передустановку VST модуля + Відкрити передустановку VST плагіна + Click here, if you want to open another *.fxp, *.fxb VST-plugin preset. - Відкрити інший .fxp. fxb VST плагін передустановки. + Відкрити іншу .fxp . fxb передустановку VST. + Previous (-) Попередній <-> + + Click here, if you want to switch to another VST-plugin preset program. - Натисніть тут для перемикання на іншу передустановку програми VST плагіна. + Перемикання на іншу передустановку програми VST плагіна. + Save preset Зберегти передустановку + Click here, if you want to save current VST-plugin preset program. Зберегти поточну передустановку програми VST плагіна. + Next (+) Наступний <+> + Click here to select presets that are currently loaded in VST. - Вибір з уже завантажених в VST передустановок. + Вибір із уже завантажених в VST предустановок. + + Show/hide GUI + Показати / приховати інтерфейс + + + + Click here to show or hide the graphical user interface (GUI) of your VST-plugin. + Приховує / показує графічний користувальницький інтерфейс (GUI) обраного модуля VST. + + + + Turn off all notes + Вимкнути всі ноти + + + + Open VST-plugin + Відкрити модуль VST + + + + DLL-files (*.dll) + Бібліотеки DLL (*.dll) + + + + EXE-files (*.exe) + Програми EXE (*.exe) + + + + No VST-plugin loaded + Модуль VST не завантажений + + + Preset Передустановка + by від + - VST plugin control - Управління VST плагіном @@ -7284,10 +9232,12 @@ Please make sure you have read-permission to the file and the directory containi VisualizationWidget + click to enable/disable visualization of master-output Натисніть, щоб увімкнути/вимкнути візуалізацію головного виводу + Click to enable Натисніть для включення @@ -7295,54 +9245,69 @@ Please make sure you have read-permission to the file and the directory containi VstEffectControlDialog + Show/hide Показати/Сховати + Control VST-plugin from LMMS host Управління VST плагіном через LMMS хост + Click here, if you want to control VST-plugin from host. Натисніть тут, для контролю VST плагіном через хост. + Open VST-plugin preset Відкрити передустановку VST плагіна + Click here, if you want to open another *.fxp, *.fxb VST-plugin preset. Відкрити іншу .fxp . fxb передустановку VST. + Previous (-) Попередній <-> + + Click here, if you want to switch to another VST-plugin preset program. Перемикання на іншу передустановку програми VST плагіна. + Next (+) Наступний <+> + Click here to select presets that are currently loaded in VST. Вибір із уже завантажених в VST предустановок. + Save preset Зберегти налаштування + Click here, if you want to save current VST-plugin preset program. Зберегти поточну передустановку програми VST плагіна. + + Effect by: Ефекти по: + &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /> @@ -7350,173 +9315,217 @@ Please make sure you have read-permission to the file and the directory containi VstPlugin - Loading plugin - Завантаження модуля + + + The VST plugin %1 could not be loaded. + VST плагін %1 не може бути завантажено. + Open Preset Відкрити предустановку + + Vst Plugin Preset (*.fxp *.fxb) Передустановка VST плагіна (*.fxp, *.fxb) + : default : основні + " " + ' ' + Save Preset Зберегти предустановку + .fxp .fxp + .FXP .FXP + .FXB .FXB + .fxb .fxb - Please wait while loading VST plugin... - Будь ласка, зачекайте доки завантажується VST плагін ... + + Loading plugin + Завантаження модуля - The VST plugin %1 could not be loaded. - VST плагін %1 не може бути завантажено. + + Please wait while loading VST plugin... + Будь ласка, зачекайте доки завантажується VST плагін ... WatsynInstrument + Volume A1 Гучність A1 + Volume A2 Гучність A2 + Volume B1 Гучність B1 + Volume B2 Гучність B2 + Panning A1 Баланс A1 + Panning A2 Баланс A2 + Panning B1 Баланс B1 + Panning B2 Баланс B2 + Freq. multiplier A1 Множник частоти A1 + Freq. multiplier A2 Множник частоти A2 + Freq. multiplier B1 Множник частоти B1 + Freq. multiplier B2 Множник частоти B2 + Left detune A1 Ліве підстроювання A1 + Left detune A2 Ліве підстроювання A2 + Left detune B1 Ліве підстроювання B1 + Left detune B2 Ліве підстроювання B2 + Right detune A1 Праве підстроювання A1 + Right detune A2 Праве підстроювання A2 + Right detune B1 Праве підстроювання B1 + Right detune B2 Праве підстроювання B2 + A-B Mix A-B Мікс + A-B Mix envelope amount A-B Мікс кіл. обвідної + A-B Mix envelope attack A-B Мікс атаки обвідної + A-B Mix envelope hold A-B Мікс утримання обвідної + A-B Mix envelope decay A-B Мікс згасання обвідної + A1-B2 Crosstalk Перехресні перешкоди A1-B2 + A2-A1 modulation Модуляція A2-A1 + B2-B1 modulation Модуляція B2-B1 + Selected graph Обраний графік @@ -7524,213 +9533,291 @@ Please make sure you have read-permission to the file and the directory containi WatsynView - Select oscillator A1 - Виберіть генератор A1 - - - Select oscillator A2 - Виберіть генератор A2 - - - Select oscillator B1 - Виберіть генератор B1 - - - Select oscillator B2 - Виберіть генератор B2 - - - Mix output of A2 to A1 - Змішати виходи A2 до A1 - - - Modulate amplitude of A1 with output of A2 - Модулювати амплітуду А1 виходом з А2 - - - Ring-modulate A1 and A2 - Кільцева модуляція А1 і А2 - - - Modulate phase of A1 with output of A2 - Модулювати фазу А1 виходом з А2 - - - Mix output of B2 to B1 - Змішати виходи В2 до В1 - - - Modulate amplitude of B1 with output of B2 - Модулювати амплітуду В1 виходом з В2 - - - Ring-modulate B1 and B2 - Кільцева модуляція В1 і В2 - - - Modulate phase of B1 with output of B2 - Модулювати фазу В1 виходом з В2 - - - Draw your own waveform here by dragging your mouse on this graph. - Тут ви можете малювати власний сигнал. - - - Load waveform - Завантаження форми звуку - - - Click to load a waveform from a sample file - Натисніть для завантаження форми звуку з файлу із зразком - - - Phase left - Фаза зліва - - - Click to shift phase by -15 degrees - Натисніть, щоб змістити фазу на -15 градусів - - - Phase right - Фаза праворуч - - - Click to shift phase by +15 degrees - Натисніть, щоб змістити фазу на +15 градусів - - - Normalize - Нормалізувати - - - Click to normalize - Натисніть для нормалізації - - - Invert - Інвертувати - - - Click to invert - Натисніть щоб інвертувати - - - Smooth - Згладити - - - Click to smooth - Натисніть щоб згладити - - - Sine wave - Синусоїда - - - Click for sine wave - Згенерувати гармонійний (синусоїдальний) сигнал - - - Triangle wave - Трикутна хвиля - - - Click for triangle wave - Згенерувати трикутний сигнал - - - Click for saw wave - Згенерувати зигзагоподібний сигнал - - - Square wave - Квадратна хвиля - - - Click for square wave - Згенерувати квадратний сигнал - - + + + + Volume Гучність + + + + Panning Баланс + + + + Freq. multiplier Множник частоти + + + + Left detune Ліве підстроювання + + + + + + + + cents відсотків + + + + Right detune Праве підстроювання + A-B Mix A-B Мікс + Mix envelope amount Мікс кількості обвідної + Mix envelope attack A-B Мікс вступу обвідної + Mix envelope hold A-B Мікс утримання обвідної + Mix envelope decay A-B Мікс згасання обвідної + Crosstalk Перехід + + + Select oscillator A1 + Виберіть генератор A1 + + + + Select oscillator A2 + Виберіть генератор A2 + + + + Select oscillator B1 + Виберіть генератор B1 + + + + Select oscillator B2 + Виберіть генератор B2 + + + + Mix output of A2 to A1 + Змішати виходи A2 до A1 + + + + Modulate amplitude of A1 with output of A2 + Модулювати амплітуду А1 виходом з А2 + + + + Ring-modulate A1 and A2 + Кільцева модуляція А1 і А2 + + + + Modulate phase of A1 with output of A2 + Модулювати фазу А1 виходом з А2 + + + + Mix output of B2 to B1 + Змішати виходи В2 до В1 + + + + Modulate amplitude of B1 with output of B2 + Модулювати амплітуду В1 виходом з В2 + + + + Ring-modulate B1 and B2 + Кільцева модуляція В1 і В2 + + + + Modulate phase of B1 with output of B2 + Модулювати фазу В1 виходом з В2 + + + + + + + Draw your own waveform here by dragging your mouse on this graph. + Тут ви можете малювати власний сигнал. + + + + Load waveform + Завантаження форми звуку + + + + Click to load a waveform from a sample file + Натисніть для завантаження форми звуку з файлу із зразком + + + + Phase left + Фаза зліва + + + + Click to shift phase by -15 degrees + Натисніть, щоб змістити фазу на -15 градусів + + + + Phase right + Фаза праворуч + + + + Click to shift phase by +15 degrees + Натисніть, щоб змістити фазу на +15 градусів + + + + Normalize + Нормалізувати + + + + Click to normalize + Натисніть для нормалізації + + + + Invert + Інвертувати + + + + Click to invert + Натисніть щоб інвертувати + + + + Smooth + Згладити + + + + Click to smooth + Натисніть щоб згладити + + + + Sine wave + Синусоїда + + + + Click for sine wave + Згенерувати гармонійний (синусоїдальний) сигнал + + + + + Triangle wave + Трикутна хвиля + + + + Click for triangle wave + Згенерувати трикутний сигнал + + + + Click for saw wave + Згенерувати зигзагоподібний сигнал + + + + Square wave + Квадратна хвиля + + + + Click for square wave + Згенерувати квадратний сигнал + ZynAddSubFxInstrument + Portamento Портаменто + Filter Frequency Фільтр Частот + Filter Resonance Фільтр резонансу + Bandwidth Ширина смуги + FM Gain Підсил FM + Resonance Center Frequency Частоти центру резонансу + Resonance Bandwidth Ширина смуги резонансу + Forward MIDI Control Change Events Переслати зміну подій MIDI управління @@ -7738,121 +9825,150 @@ Please make sure you have read-permission to the file and the directory containi ZynAddSubFxView - Show GUI - Показати інтерфейс - - - Click here to show or hide the graphical user interface (GUI) of ZynAddSubFX. - Натисніть сюди щоб сховати чи показати графічний інтерфейс ZynAddSubFX. - - + Portamento: Портаменто: + PORT PORT + Filter Frequency: Фільтр частот: + FREQ FREQ + Filter Resonance: Фільтр резонансу: + RES RES + Bandwidth: Смуга пропускання: + BW BW + FM Gain: Підсилення частоти модуляції (FM): + FM GAIN FM GAIN + Resonance center frequency: Частота центру резонансу: + RES CF RES CF + Resonance bandwidth: Ширина смуги резонансу: + RES BW RES BW + Forward MIDI Control Changes Переслати зміну подій MiDi управління + + + Show GUI + Показати інтерфейс + + + + Click here to show or hide the graphical user interface (GUI) of ZynAddSubFX. + Натисніть сюди щоб сховати чи показати графічний інтерфейс ZynAddSubFX. + audioFileProcessor + Amplify Підсилення + Start of sample Початок запису + End of sample Кінець запису - Reverse sample - Перевернути запис - - - Stutter - Заїкання - - + Loopback point Точка повернення з повтору + + Reverse sample + Перевернути запис + + + Loop mode Режим повтору + + Stutter + Заїкання + + + Interpolation mode Режим Інтерполяції + None Нічого + Linear Лінійний + Sinc Синхронізований + Sample not found: %1 Запис не знайдено: %1 @@ -7860,6 +9976,7 @@ Please make sure you have read-permission to the file and the directory containi bitInvader + Samplelength Тривалість @@ -7867,165 +9984,205 @@ Please make sure you have read-permission to the file and the directory containi bitInvaderView + Sample Length Тривалість запису - Sine wave - Синусоїда - - - Triangle wave - Трикутник - - - Saw wave - Зигзаг - - - Square wave - Квадрат - - - White noise wave - Білий шум - - - User defined wave - Користувацька - - - Smooth - Згладити - - - Click here to smooth waveform. - Клацніть щоб згладити форму сигналу. - - - Interpolation - Інтерполяція - - - Normalize - Нормалізувати - - + Draw your own waveform here by dragging your mouse on this graph. Тут ви можете малювати власний сигнал. - Click for a sine-wave. - Згенерувати гармонійний (синусоїдальний) сигнал. + + Sine wave + Синусоїда + + Click for a sine-wave. + Генерувати гармонійний (синусоїдальний) сигнал. + + + + Triangle wave + Трикутник + + + Click here for a triangle-wave. Згенерувати трикутний сигнал. + + Saw wave + Зигзаг + + + Click here for a saw-wave. - Згенерувати зигзагоподібний сигнал. + Згенерувати зигзаг. + + Square wave + Квадрат + + + Click here for a square-wave. - Згенерувати квадратну хвилю. + Згенерувати квадратний сигнал. + + White noise wave + Білий шум + + + Click here for white-noise. Згенерувати білий шум. + + User defined wave + Користувацька + + + Click here for a user-defined shape. Задати форму сигналу вручну. + + + Smooth + Згладити + + + + Click here to smooth waveform. + Клацніть щоб згладити форму сигналу. + + + + Interpolation + Інтерполяція + + + + Normalize + Нормалізувати + dynProcControlDialog + INPUT ВХІД + Input gain: Вхідне підсилення: + OUTPUT ВИХІД + Output gain: Вихідне підсилення: + ATTACK ВСТУП + Peak attack time: Час пікової атаки: + RELEASE ЗМЕНШЕННЯ + Peak release time: Час відпуску піку: + Reset waveform Скидання сигналу + Click here to reset the wavegraph back to default Натисніть тут, щоб скинути граф хвилі назад за замовчуванням + Smooth waveform Згладжений сигнал + Click here to apply smoothing to wavegraph Натисніть тут, щоб застосувати згладжування графа хвилі + Increase wavegraph amplitude by 1dB Збільште амплітуди графа хвилі на 1дБ + Click here to increase wavegraph amplitude by 1dB Натисніть тут, щоб збільшити амплітуду графа хвилі на 1дБ + Decrease wavegraph amplitude by 1dB Зменшення амплітуди графа хвилі на 1дБ + Click here to decrease wavegraph amplitude by 1dB Натисніть тут, щоб зменшити амплітуду графа хвилі на 1дБ + Stereomode Maximum Максимальний стереорежим + Process based on the maximum of both stereo channels Процес заснований на максимумі від обох каналів + Stereomode Average Середній стереорежим + Process based on the average of both stereo channels Процес заснований на середньому обох каналів + Stereomode Unlinked Розімкнений стереорежим + Process each stereo channel independently Обробляє кожен стерео канал незалежно @@ -8033,22 +10190,27 @@ Please make sure you have read-permission to the file and the directory containi dynProcControls + Input gain Вхідне підсилення + Output gain Вихідне підсилення + Attack time Час вступу + Release time Час зменшення + Stereo mode Стерео режим @@ -8183,10 +10345,12 @@ Please make sure you have read-permission to the file and the directory containi fxLineLcdSpinBox + Assign to: Призначити до: + New FX Channel Новий ефект каналу @@ -8194,6 +10358,7 @@ Please make sure you have read-permission to the file and the directory containi graphModel + Graph Графік @@ -8201,50 +10366,62 @@ Please make sure you have read-permission to the file and the directory containi kickerInstrument + Start frequency Початкова частота + End frequency Кінцева частота - Gain - Підсилення - - + Length Довжина + Distortion Start Початкове спотворення + Distortion End Кінцеве спотворення + + Gain + Підсилення + + + Envelope Slope Нахил обвідної + Noise Шум + Click Натисніть + Frequency Slope Частота нахилу + Start from note Почати з замітки + End to note Закінчити заміткою @@ -8252,42 +10429,52 @@ Please make sure you have read-permission to the file and the directory containi kickerInstrumentView + Start frequency: Початкова частота: + End frequency: Кінцева частота: - Gain: - Підсилення: - - + Frequency Slope: Частота нахилу: + + Gain: + Підсилення: + + + Envelope Length: Довжина обвідної: + Envelope Slope: Нахил обвідної: + Click: Натиснення: + Noise: Шум: + Distortion Start: Початкове спотворення: + Distortion End: Кінцеве спотворення: @@ -8295,26 +10482,37 @@ Please make sure you have read-permission to the file and the directory containi ladspaBrowserView + + Available Effects Доступні ефекти + + Unavailable Effects Недоступні ефекти + + Instruments Інструменти + + Analysis Tools Аналізатори + + Don't know Невідомі + This dialog displays information on all of the LADSPA plugins LMMS was able to locate. The plugins are divided into five categories based upon an interpretation of the port types and names. Available Effects are those that can be used by LMMS. In order for LMMS to be able to use an effect, it must, first and foremost, be an effect, which is to say, it has to have both input channels and output channels. LMMS identifies an input channel as an audio rate port containing 'in' in the name. Output channels are identified by the letters 'out'. Furthermore, the effect must have the same number of inputs and outputs and be real time capable. @@ -8343,6 +10541,7 @@ Double clicking any of the plugins will bring up information on the ports. + Type: Тип: @@ -8350,10 +10549,12 @@ Double clicking any of the plugins will bring up information on the ports. ladspaDescription + Plugins Модулі + Description Опис @@ -8361,66 +10562,83 @@ Double clicking any of the plugins will bring up information on the ports. ladspaPortDialog + Ports Порти + Name І'мя + Rate Частота вибірки + Direction Напрямок + Type Тип + Min < Default < Max Менше < Стандарт <Більше + Logarithmic Логарифмічний + SR Dependent Залежність від SR + Audio Аудіо + Control Управління + Input Ввід + Output Вивід + Toggled Увімкнено + Integer Ціле + Float Дробове + + Yes Так @@ -8428,46 +10646,57 @@ Double clicking any of the plugins will bring up information on the ports. lb302Synth + VCF Cutoff Frequency Частота зрізу VCF + VCF Resonance Посилення VCF + VCF Envelope Mod Модуляція обвідної VCF + VCF Envelope Decay Спад обвідної VCF + Distortion Спотворення + Waveform Форма хвилі + Slide Decay Зміщення згасання + Slide Зміщення + Accent Акцент + Dead Глухо + 24dB/oct Filter 24дБ/окт фільтр @@ -8475,122 +10704,153 @@ Double clicking any of the plugins will bring up information on the ports. lb302SynthView + Cutoff Freq: Частота зрізу: + Resonance: Резонанс: + Env Mod: Мод Обвідної: + Decay: Згасання: + 303-es-que, 24dB/octave, 3 pole filter 303-ій, 24дБ/октаву, 3-польний фільтр + Slide Decay: Зміщення згасання: + DIST: СПОТ: + Saw wave Зигзаг + Click here for a saw-wave. Згенерувати зигзаг. + Triangle wave Трикутна хвиля + Click here for a triangle-wave. Згенерувати трикутний сигнал. + Square wave Квадрат + Click here for a square-wave. Згенерувати квадратний сигнал. + Rounded square wave Хвиля округленого квадрату + Click here for a square-wave with a rounded end. Створити квадратну хвилю закруглену в кінці. + Moog wave Муг хвиля + Click here for a moog-like wave. Згенерувати хвилю схожу на муг. + Sine wave Синусоїда + Click for a sine-wave. Генерувати гармонійний (синусоїдальний) сигнал. + + White noise wave Білий шум + Click here for an exponential wave. Генерувати експонентний сигнал. + Click here for white-noise. Згенерувати білий шум. + Bandlimited saw wave Зигзаг хвиля з обмеженою смугою + Click here for bandlimited saw wave. Натисніть тут для пилкоподібної хвилі з обмеженою смугою. + Bandlimited square wave Квадратна хвиля з обмеженою смугою + Click here for bandlimited square wave. Натисніть тут для квадратної хвилі з обмеженою смугою. + Bandlimited triangle wave Трикутна хвиля з обмеженою смугою + Click here for bandlimited triangle wave. Натисніть тут для трикутної хвилі з обмеженою смугою. + Bandlimited moog saw wave Муг-зигзаг хвиля з обмеженою смугою + Click here for bandlimited moog saw wave. Натисніть тут для муг-зигзаг хвилі з обмеженою смугою. @@ -8598,118 +10858,147 @@ Double clicking any of the plugins will bring up information on the ports. malletsInstrument + Hardness Жорсткість + Position Положення + Vibrato Gain Посилення вібрато + Vibrato Freq Частота вібрато + Stick Mix Зведення рученят + Modulator Модулятор + Crossfade Перехід + LFO Speed Швидкість LFO + LFO Depth Глибина LFO + ADSR ADSR + Pressure Тиск + Motion Рух + Speed Швидкість + Bowed Нахил + Spread Розкид + Marimba Марімба + Vibraphone Віброфон + Agogo Дискотека + Wood1 Дерево1 + Reso Ресо + Wood2 Дерево2 + Beats Удари + Two Fixed Два фіксованих + Clump Важка хода + Tubular Bells Трубні дзвони + Uniform Bar Рівномірні смуги + Tuned Bar Підстроєні смуги + Glass Скло + Tibetan Bowl Тибетські кулі @@ -8717,149 +11006,186 @@ Double clicking any of the plugins will bring up information on the ports. malletsInstrumentView + Instrument Інструмент + Spread Розкид + Spread: Розкид: - Hardness - Жорсткість - - - Hardness: - Жорсткість: - - - Position - Положення - - - Position: - Положення: - - - Vib Gain - Підс. вібрато - - - Vib Gain: - Підс. вібрато: - - - Vib Freq - Част. віб - - - Vib Freq: - Вібрато: - - - Stick Mix - Зведення рученят - - - Stick Mix: - Зведення рученят: - - - Modulator - Модулятор - - - Modulator: - Модулятор: - - - Crossfade - Перехід - - - Crossfade: - Перехід: - - - LFO Speed - Швидкість LFO - - - LFO Speed: - Швидкість LFO: - - - LFO Depth - Глибина LFO - - - LFO Depth: - Глибина LFO: - - - ADSR - ADSR - - - ADSR: - ADSR: - - - Pressure - Тиск - - - Pressure: - Тиск: - - - Speed - Швидкість - - - Speed: - Швидкість: - - + Missing files Відсутні файли + Your Stk-installation seems to be incomplete. Please make sure the full Stk-package is installed! Схоже, що встановлені не всі пакети Stk. Вам слід це перевірити! + + + Hardness + Жорсткість + + + + Hardness: + Жорсткість: + + + + Position + Положення + + + + Position: + Положення: + + + + Vib Gain + Підс. вібрато + + + + Vib Gain: + Підс. вібрато: + + + + Vib Freq + Част. віб + + + + Vib Freq: + Вібрато: + + + + Stick Mix + Зведення рученят + + + + Stick Mix: + Зведення рученят: + + + + Modulator + Модулятор + + + + Modulator: + Модулятор: + + + + Crossfade + Перехід + + + + Crossfade: + Перехід: + + + + LFO Speed + Швидкість LFO + + + + LFO Speed: + Швидкість LFO: + + + + LFO Depth + Глибина LFO + + + + LFO Depth: + Глибина LFO: + + + + ADSR + ADSR + + + + ADSR: + ADSR: + + + + Pressure + Тиск + + + + Pressure: + Тиск: + + + + Speed + Швидкість + + + + Speed: + Швидкість: + manageVSTEffectView + - VST parameter control Управление VST параметрами + VST Sync VST синхронізація + Click here if you want to synchronize all parameters with VST plugin. Натисніть тут для синхронізації всіх параметрів VST плагіна. + + Automated Автоматизовано + Click here if you want to display automated parameters only. Натисніть тут, якщо хочете бачити тільки автоматизовані параметри. + Close Закрити + Close VST effect knob-controller window. Закрити вікно управління регуляторами VST плагіна. @@ -8867,30 +11193,39 @@ Double clicking any of the plugins will bring up information on the ports. manageVestigeInstrumentView + + - VST plugin control Управління VST плагіном + VST Sync VST синхронізація + Click here if you want to synchronize all parameters with VST plugin. Натисніть тут для синхронізації всіх параметрів VST плагіна. + + Automated Автоматизовано + Click here if you want to display automated parameters only. Натисніть тут, якщо хочете бачити тільки автоматизовані параметри. + Close Закрити + Close VST plugin knob-controller window. Закрити вікно управління регуляторами VST плагіна. @@ -8898,118 +11233,147 @@ Double clicking any of the plugins will bring up information on the ports. opl2instrument + Patch Патч + Op 1 Attack ОП 1 Вступ + Op 1 Decay ОП 1 Спад + Op 1 Sustain ОП 1 Видержка + Op 1 Release ОП 1 Зменшення + Op 1 Level ОП 1 Рівень + Op 1 Level Scaling ОП 1 Рівень збільшення + Op 1 Frequency Multiple ОП 1 Множник частот + Op 1 Feedback ОП 1 Повернення + Op 1 Key Scaling Rate ОП 1 Ключова ставка множника + Op 1 Percussive Envelope ОП 1 Ударна обвідна + Op 1 Tremolo ОП 1 Тремоло + Op 1 Vibrato Оп 1 Вібрато + Op 1 Waveform ОП 1 Хвиля + Op 2 Attack ОП 2 Вступ + Op 2 Decay ОП 2 Спад + Op 2 Sustain ОП 2 Видержка + Op 2 Release ОП 2 Зменшення + Op 2 Level ОП 2 Рівень + Op 2 Level Scaling ОП 2 Рівень збільшення + Op 2 Frequency Multiple ОП 2 Множник частот + Op 2 Key Scaling Rate ОП 2 Ключова ставка множника + Op 2 Percussive Envelope ОП 2 Ударна обвідна + Op 2 Tremolo ОП 2 Тремоло + Op 2 Vibrato Оп 2 Вібрато + Op 2 Waveform ОП 2 Хвиля + FM FM + Vibrato Depth Глибина вібрато + Tremolo Depth Глибина тремоло @@ -9017,18 +11381,26 @@ Double clicking any of the plugins will bring up information on the ports. opl2instrumentView + + Attack Вступ + + Decay Згасання + + Release Зменшення + + Frequency multiplier Множник частоти @@ -9036,10 +11408,12 @@ Double clicking any of the plugins will bring up information on the ports. organicInstrument + Distortion Спотворення + Volume Гучність @@ -9047,50 +11421,63 @@ Double clicking any of the plugins will bring up information on the ports. organicInstrumentView + Distortion: Спотворення: - Volume: - Гучність: - - - Randomise - Випадково - - - Osc %1 waveform: - Форма сигналу осциллятора %1: - - - Osc %1 volume: - Гучність осциллятора %1: - - - Osc %1 panning: - Баланс для осциллятора %1: - - - cents - соті - - + The distortion knob adds distortion to the output of the instrument. Спотворення додає спотворення до виходу інструменту. + + Volume: + Гучність: + + + The volume knob controls the volume of the output of the instrument. It is cumulative with the instrument window's volume control. Регулятор гучності виведення інструменту, підсумовується з регулятором гучності вікна інструменту. + + Randomise + Випадково + + + The randomize button randomizes all knobs except the harmonics,main volume and distortion knobs. Кнопка рандомізації випадково встановлює всі регулятори, крім гармонік, основної гучності і регулятора спотворень. + + + Osc %1 waveform: + Форма сигналу осциллятора %1: + + + + Osc %1 volume: + Гучність осциллятора %1: + + + + Osc %1 panning: + Баланс для осциллятора %1: + + + Osc %1 stereo detuning Осц %1 стерео расстройка + + cents + соті + + + Osc %1 harmonic: Осц %1 гармоніка: @@ -9098,265 +11485,351 @@ Double clicking any of the plugins will bring up information on the ports. FreeBoyInstrument + Sweep time Час поширення + Sweep direction Напрям поширення + Sweep RtShift amount - Кіль-ть поширення зсуву вправо + Кіл-ть розгортки зсуву вправо + + Wave Pattern Duty Робоча форма хвилі + Channel 1 volume Гучність першого каналу + + + Volume sweep direction Обсяг напрямку поширення + + + Length of each step in sweep - Довжина кожного такту в поширенні + Довжина кожного кроку в розгортці + Channel 2 volume Гучність другого каналу + Channel 3 volume Гучність третього каналу + Channel 4 volume Гучність четвертого каналу + + Shift Register width + Зміщення ширини регістра + + + Right Output level Вихідний рівень праворуч + Left Output level Вихідний рівень зліва + Channel 1 to SO2 (Left) Від першого каналу до SO2 (лівий канал) + Channel 2 to SO2 (Left) Від другого каналу до SO2 (лівий канал) + Channel 3 to SO2 (Left) Від третього каналу до SO2 (лівий канал) + Channel 4 to SO2 (Left) Від четвертого каналу до SO2 (лівий канал) + Channel 1 to SO1 (Right) Від першого каналу до SO1 (правий канал) + Channel 2 to SO1 (Right) Від другого каналу до SO1 (правий канал) + Channel 3 to SO1 (Right) Від третього каналу до SO1 (правий канал) + Channel 4 to SO1 (Right) Від четвертого каналу до SO1 (правий канал) + Treble Дискант + Bass Бас - - Shift Register width - Зміщення ширини регістра - FreeBoyInstrumentView + Sweep Time: Час розгортки: + Sweep Time Час розгортки - Sweep RtShift amount: - Кіл-ть розгортки зміщення вправо: - - - Sweep RtShift amount - Кіл-ть розгортки зсуву вправо - - - Wave pattern duty: - Робоча форма хвилі: - - - Wave Pattern Duty - Робоча форма хвилі - - - Square Channel 1 Volume: - Гучність квадратного каналу 1: - - - Length of each step in sweep: - Довжина кожного кроку в розгортці: - - - Length of each step in sweep - Довжина кожного кроку в розгортці - - - Wave pattern duty - Робоча форма хвилі - - - Square Channel 2 Volume: - Гучність квадратного каналу 2: - - - Square Channel 2 Volume - Гучність квадратного каналу 2 - - - Wave Channel Volume: - Гучність хвильового каналу: - - - Wave Channel Volume - Гучність хвильового каналу - - - Noise Channel Volume: - Гучність каналу шуму: - - - Noise Channel Volume - Гучність каналу шуму - - - SO1 Volume (Right): - Гучність SO1 (Правий): - - - SO1 Volume (Right) - Гучність SO1 (Правий) - - - SO2 Volume (Left): - Гучність SO2 (Лівий): - - - SO2 Volume (Left) - Гучність SO2 (Лівий) - - - Treble: - Дискант: - - - Treble - Дискант - - - Bass: - Бас: - - - Bass - Бас - - - Sweep Direction - Напрямок розгортки - - - Volume Sweep Direction - Гучність напрямки розгортки - - - Shift Register Width - Зміщення ширини регістра - - - Channel1 to SO1 (Right) - Канал1 в SO1 (Правий) - - - Channel2 to SO1 (Right) - Канал2 в SO1 (Правий) - - - Channel3 to SO1 (Right) - Канал3 в SO1 (Правий) - - - Channel4 to SO1 (Right) - Канал4 в SO1 (Правий) - - - Channel1 to SO2 (Left) - Канал1 в SO2 (Лівий) - - - Channel2 to SO2 (Left) - Канал2 в SO2 (Лівий) - - - Channel3 to SO2 (Left) - Канал3 в SO2 (Лівий) - - - Channel4 to SO2 (Left) - Канал4 в SO2 (Лівий) - - - Wave Pattern - Малюнок хвилі - - + The amount of increase or decrease in frequency Кіл-ть збільшення або зменшення в частоті + + Sweep RtShift amount: + Кіл-ть розгортки зміщення вправо: + + + + Sweep RtShift amount + Кіл-ть розгортки зсуву вправо + + + The rate at which increase or decrease in frequency occurs Темп прояви збільшення або зниження в частоті + + + Wave pattern duty: + Робоча форма хвилі: + + + + Wave Pattern Duty + Робоча форма хвилі + + + + The duty cycle is the ratio of the duration (time) that a signal is ON versus the total period of the signal. Робочий цикл це коефіцієнт тривалості (часу) включеного сигналу відносно всього періоду сигналу. + + + Square Channel 1 Volume: + Гучність квадратного каналу 1: + + + Square Channel 1 Volume Гучність квадратного каналу 1 + + + + Length of each step in sweep: + Довжина кожного кроку в розгортці: + + + + + + Length of each step in sweep + Довжина кожного кроку в розгортці + + + + + The delay between step change Затримка між змінами кроку + + Wave pattern duty + Робоча форма хвилі + + + + Square Channel 2 Volume: + Гучність квадратного каналу 2: + + + + + Square Channel 2 Volume + Гучність квадратного каналу 2 + + + + Wave Channel Volume: + Гучність хвильового каналу: + + + + + Wave Channel Volume + Гучність хвильового каналу + + + + Noise Channel Volume: + Гучність каналу шуму: + + + + + Noise Channel Volume + Гучність каналу шуму + + + + SO1 Volume (Right): + Гучність SO1 (Правий): + + + + SO1 Volume (Right) + Гучність SO1 (Правий) + + + + SO2 Volume (Left): + Гучність SO2 (Лівий): + + + + SO2 Volume (Left) + Гучність SO2 (Лівий) + + + + Treble: + Дискант: + + + + Treble + Дискант + + + + Bass: + Бас: + + + + Bass + Бас + + + + Sweep Direction + Напрямок розгортки + + + + + + + + Volume Sweep Direction + Гучність напрямки розгортки + + + + Shift Register Width + Зміщення ширини регістра + + + + Channel1 to SO1 (Right) + Канал1 в SO1 (Правий) + + + + Channel2 to SO1 (Right) + Канал2 в SO1 (Правий) + + + + Channel3 to SO1 (Right) + Канал3 в SO1 (Правий) + + + + Channel4 to SO1 (Right) + Канал4 в SO1 (Правий) + + + + Channel1 to SO2 (Left) + Канал1 в SO2 (Лівий) + + + + Channel2 to SO2 (Left) + Канал2 в SO2 (Лівий) + + + + Channel3 to SO2 (Left) + Канал3 в SO2 (Лівий) + + + + Channel4 to SO2 (Left) + Канал4 в SO2 (Лівий) + + + + Wave Pattern + Малюнок хвилі + + + Draw the wave here Малювати хвилю тут @@ -9364,34 +11837,42 @@ Double clicking any of the plugins will bring up information on the ports. patchesDialog + Qsynth: Channel Preset Q-Синтезатор: Канал передустановлено + Bank selector Селектор банку + Bank Банк + Program selector Селектор програм + Patch Патч + Name І'мя + OK ОК + Cancel Скасувати @@ -9399,186 +11880,231 @@ Double clicking any of the plugins will bring up information on the ports. pluginBrowser + no description опис відсутній - Incomplete monophonic imitation tb303 - Незавершена монофонічна імітація tb303 + + A native amplifier plugin + Рідний плагін підсилення - Plugin for freely manipulating stereo output - Модуль для довільного управління стереовиходом + + Simple sampler with various settings for using samples (e.g. drums) in an instrument-track + Простий семплер з різними налаштуваннями для використання записів (наприклад, ударні) в інструментальному трекі - Plugin for controlling knobs with sound peaks - Модуль для встановлення значень регуляторів на піках гучності + + Boost your bass the fast and simple way + Накачай свій бас швидко і просто - Plugin for enhancing stereo separation of a stereo input file - Модуль, що підсилює різницю між каналами стереозапису + + Customizable wavetable synthesizer + Налаштовуваний синтезатор звукозаписів (wavetable) + + An oversampling bitcrusher + Перевибірка малого дробдення + + + + Carla Patchbay Instrument + Carla Комутаційний інструмент + + + + Carla Rack Instrument + Carla підставочний інструмент + + + + A 4-band Crossover Equalizer + 4-смуговий еквалайзер Кросовер + + + + A native delay plugin + Рідний плагін затримки + + + + A Dual filter plugin + Плагін подвійного фільтру + + + + plugin for processing dynamics in a flexible way + плагін для обробки динаміки гнучким методом + + + + A native eq plugin + Рідний eq плагін + + + + A native flanger plugin + Рідний фланжер плагін + + + + Player for GIG files + Програвач GIG файлів + + + + Filter for importing Hydrogen files into LMMS + Фільтр для імпорту Hydrogen файлів в LMMS + + + + Versatile drum synthesizer + Універсальний барабанний синтезатор + + + List installed LADSPA plugins Показати встановлені модулі LADSPA - GUS-compatible patch instrument - Патч-інструмент, сумісний з GUS - - - Additive Synthesizer for organ-like sounds - Синтезатор звуків нашталт органу - - - Tuneful things to bang on - Мелодійні ударні - - - VST-host for using VST(i)-plugins within LMMS - VST - хост для підтримки модулів VST(i) в LMMS - - - Vibrating string modeler - Емуляція вібруючих струн - - + plugin for using arbitrary LADSPA-effects inside LMMS. Модуль, що дозволяє використовувати в LMMS будь які ефекти LADSPA. + + Incomplete monophonic imitation tb303 + Незавершена монофонічна імітація tb303 + + + + Filter for exporting MIDI-files from LMMS + Фільтри для експорту MIDI-файлів з LMMS + + + Filter for importing MIDI-files into LMMS Фільтр для включення файлу MIDI в проект ЛММС + + Monstrous 3-oscillator synth with modulation matrix + Монстро 3-осцилляторний синт з матрицею модуляції + + + + A multitap echo delay plugin + Плагін багаторазової послідовної затримки відлуння + + + + A NES-like synthesizer + NES-подібний синтезатор + + + + 2-operator FM Synth + 2-режимний синт модуляції частот (FM synth) + + + + Additive Synthesizer for organ-like sounds + Синтезатор звуків нашталт органу + + + + Emulation of GameBoy (TM) APU + Емуляція GameBoy (ТМ) + + + + GUS-compatible patch instrument + Патч-інструмент, сумісний з GUS + + + + Plugin for controlling knobs with sound peaks + Модуль для встановлення значень регуляторів на піках гучності + + + + Reverb algorithm by Sean Costello + Алгоритм реверберації Шона Костелло + + + + Player for SoundFont files + Програвач файлів SoundFont + + + + LMMS port of sfxr + LMMS порт SFXR + + + Emulation of the MOS6581 and MOS8580 SID. This chip was used in the Commodore 64 computer. Емуляція MOS6581 і MOS8580. Використовувалося на комп'ютері Commodore 64. - Player for SoundFont files - Програвач файлів SoundFont - - - Emulation of GameBoy (TM) APU - Емуляція GameBoy (ТМ) - - - Customizable wavetable synthesizer - Налаштовуваний синтезатор звукозаписів (wavetable) - - - Embedded ZynAddSubFX - Вбудований ZynAddSubFX - - - 2-operator FM Synth - 2-режимний синт модуляції частот (FM synth) - - - Filter for importing Hydrogen files into LMMS - Фільтр для імпорту Hydrogen файлів в LMMS - - - LMMS port of sfxr - LMMS порт SFXR - - - Monstrous 3-oscillator synth with modulation matrix - Монстро 3-осцилляторний синт з матрицею модуляції - - - Three powerful oscillators you can modulate in several ways - Три потужних генераторів можна модулювати декількома способами - - - A native amplifier plugin - Рідний плагін підсилення - - - Carla Rack Instrument - Carla підставочний інструмент - - - 4-oscillator modulatable wavetable synth - 4-генераторний модулюючий синтезатор звукозаписів - - - plugin for waveshaping - плагін формування сигналу - - - Boost your bass the fast and simple way - Накачай свій бас швидко і просто - - - Versatile drum synthesizer - Універсальний барабанний синтезатор - - - Simple sampler with various settings for using samples (e.g. drums) in an instrument-track - Простий семплер з різними налаштуваннями для використання записів (наприклад, ударні) в інструментальному трекі - - - plugin for processing dynamics in a flexible way - плагін для обробки динаміки гнучким методом - - - Carla Patchbay Instrument - Carla Комутаційний інструмент - - - plugin for using arbitrary VST effects inside LMMS. - плагін для використання довільних VST ефектів всередині LMMS. - - + Graphical spectrum analyzer plugin Плагін графічного аналізу спектру - A NES-like synthesizer - NES-подібний синтезатор + + Plugin for enhancing stereo separation of a stereo input file + Модуль, що підсилює різницю між каналами стереозапису - A native delay plugin - Рідний плагін затримки + + Plugin for freely manipulating stereo output + Модуль для довільного управління стереовиходом - Player for GIG files - Програвач GIG файлів + + Tuneful things to bang on + Мелодійні ударні - A multitap echo delay plugin - Плагін багаторазової послідовної затримки відлуння + + Three powerful oscillators you can modulate in several ways + Три потужних генераторів можна модулювати декількома способами - A native flanger plugin - Рідний фланжер плагін + + VST-host for using VST(i)-plugins within LMMS + VST - хост для підтримки модулів VST(i) в LMMS - An oversampling bitcrusher - Перевибірка малого дробдення + + Vibrating string modeler + Емуляція вібруючих струн - A native eq plugin - Рідний eq плагін + + plugin for using arbitrary VST effects inside LMMS. + плагін для використання довільних VST ефектів всередині LMMS. - A 4-band Crossover Equalizer - 4-смуговий еквалайзер Кросовер + + 4-oscillator modulatable wavetable synth + 4-генераторний модулюючий синтезатор звукозаписів - A Dual filter plugin - Плагін подвійного фільтру + + plugin for waveshaping + плагін формування сигналу - Filter for exporting MIDI-files from LMMS - Фільтри для експорту MIDI-файлів з LMMS - - - Reverb algorithm by Sean Costello - + + Embedded ZynAddSubFX + Вбудований ZynAddSubFX Mathematical expression parser @@ -9588,58 +12114,72 @@ This chip was used in the Commodore 64 computer. sf2Instrument + Bank Банк + Patch Патч + Gain Посилення + Reverb Луна + Reverb Roomsize Об'єм луни + Reverb Damping Загасання луни + Reverb Width Довгота луни + Reverb Level Рівень луни + Chorus Хор (Приспів) + Chorus Lines Лінії хору + Chorus Level Рівень хору + Chorus Speed Швидкість хору + Chorus Depth Глибина хору + A soundfont %1 could not be loaded. soundfont %1 не вдається завантажити. @@ -9647,74 +12187,92 @@ This chip was used in the Commodore 64 computer. sf2InstrumentView + Open other SoundFont file Відкрити інший файл SoundFront + Click here to open another SF2 file Натисніть тут щоб відкрити інший файл SF2 + Choose the patch Вибрати патч + Gain Підсилення + Apply reverb (if supported) Створити відлуння (якщо підтримується) + This button enables the reverb effect. This is useful for cool effects, but only works on files that support it. Ця кнопка включає ефект луни. Це корисно для класних ефектів, але працює не для всіх файлів. + Reverb Roomsize: Розмір приміщення: + Reverb Damping: Загасання луни: + Reverb Width: Довгота луни: + Reverb Level: Рівень відлуння: + Apply chorus (if supported) Створити ефект хору (якщо підтримується) + This button enables the chorus effect. This is useful for cool echo effects, but only works on files that support it. Ця кнопка включає ефект хору. Це корисно для класних ефектів, але працює не для всіх файлів. + Chorus Lines: Лінії хору: + Chorus Level: Рівень хору: + Chorus Speed: Швидкість хору: + Chorus Depth: Глибина хору: + Open SoundFont file Відкрити файл SoundFront + SoundFont2 Files (*.sf2) Файли SoundFont2 (*.sf2) @@ -9722,6 +12280,7 @@ This chip was used in the Commodore 64 computer. sfxrInstrument + Wave Form Форма хвилі @@ -9729,26 +12288,32 @@ This chip was used in the Commodore 64 computer. sidInstrument + Cutoff Зріз + Resonance Підсилення + Filter type Тип фільтру + Voice 3 off Голос 3 відкл + Volume Гучність + Chip model Модель чіпа @@ -9756,134 +12321,172 @@ This chip was used in the Commodore 64 computer. sidInstrumentView + Volume: Гучність: + Resonance: Підсилення: + + Cutoff frequency: Частота зрізу: + High-Pass filter Вис.ЧФ + Band-Pass filter Серед.ЧФ + Low-Pass filter Низ.ЧФ + Voice3 Off Голос 3 відкл + MOS6581 SID MOS6581 SID + MOS8580 SID MOS8580 SID + + Attack: Вступ: + Attack rate determines how rapidly the output of Voice %1 rises from zero to peak amplitude. Тривалість вступу визначає, наскільки швидко гучність %1-го голосу зростає від нуля до максимального значення. + + Decay: Згасання: + Decay rate determines how rapidly the output falls from the peak amplitude to the selected Sustain level. Тривалість спаду визначає, наскільки швидко гучність падає від максимуму до залишкового рівня. + Sustain: Витримка: + Output of Voice %1 will remain at the selected Sustain amplitude as long as the note is held. Гучність %1-го голосу залишатиметься на рівні амплітуди витримки, поки триває нота. + + Release: Зменшення: + The output of of Voice %1 will fall from Sustain amplitude to zero amplitude at the selected Release rate. Гучність %1-го голосу буде падати від залишкового рівня до нуля з вказаною тут швидкістю. + + Pulse Width: Довжина імпульсу: + The Pulse Width resolution allows the width to be smoothly swept with no discernable stepping. The Pulse waveform on Oscillator %1 must be selected to have any audible effect. Тривалість імпульсу дозволяє м'яко регулювати проходження імпульсу без помітних збоїв. Імпульсна хвиля повинна бути обрана на осцилляторі %1, щоб отримати звучання. + Coarse: Грубість: + The Coarse detuning allows to detune Voice %1 one octave up or down. Грубі налаштування дозволяють підлаштувати Голос %1 на одну октаву вгору або вниз. + Pulse Wave Пульсуюча хвиля + Triangle Wave Трикутник + SawTooth Зигзаг + Noise Шум + Sync Синхро + Sync synchronizes the fundamental frequency of Oscillator %1 with the fundamental frequency of Oscillator %2 producing "Hard Sync" effects. Синхро синхронізує фундаментальну частоту осцилляторів %1 фундаментальною частотою осциллятора %2, створюючи ефект "Залізної синхронізації". + Ring-Mod Круговий режим + Ring-mod replaces the Triangle Waveform output of Oscillator %1 with a "Ring Modulated" combination of Oscillators %1 and %2. Круговий режим замінює трикутні хвилі на виході осциллятора %1 "Круговою модуляцією" комбінацією осцилляторів %1 і %2. + Filtered Відфільтрований + When Filtered is on, Voice %1 will be processed through the Filter. When Filtered is off, Voice %1 appears directly at the output, and the Filter has no effect on it. Якщо цей прапорець встановлено, то %1-й голос буде проходити через фільтр. Інакше голос № %1 буде подаватися прямо на вихід. + Test Тест + Test, when set, resets and locks Oscillator %1 at zero until Test is turned off. Якщо «прапорець» встановлено, то %1-й осциллятор видає нульовий сигнал (поки прапорець не зніметься). @@ -9891,10 +12494,12 @@ This chip was used in the Commodore 64 computer. stereoEnhancerControlDialog + WIDE ШИРШЕ + Width: Ширина: @@ -9902,6 +12507,7 @@ This chip was used in the Commodore 64 computer. stereoEnhancerControls + Width Ширина @@ -9909,18 +12515,22 @@ This chip was used in the Commodore 64 computer. stereoMatrixControlDialog + Left to Left Vol: Від лівого на лівий: + Left to Right Vol: Від лівого на правий: + Right to Left Vol: Від правого на лівий: + Right to Right Vol: Від правого на правий: @@ -9928,18 +12538,22 @@ This chip was used in the Commodore 64 computer. stereoMatrixControls + Left to Left Від лівого на лівий + Left to Right Від лівого на правий + Right to Left Від правого на лівий + Right to Right Від правого на правий @@ -9947,10 +12561,12 @@ This chip was used in the Commodore 64 computer. vestigeInstrument + Loading plugin Завантаження модуля + Please wait while loading VST-plugin... Будь ласка зачекайте поки завантажеться модуль VST... @@ -9958,42 +12574,52 @@ This chip was used in the Commodore 64 computer. vibed + String %1 volume Гучність %1-й струни + String %1 stiffness Жорсткість %1-й струни + Pick %1 position Лад %1 + Pickup %1 position Положення %1-го звукознімача + Pan %1 Бал %1 + Detune %1 Підстроювання %1 + Fuzziness %1 Нечіткість %1 + Length %1 Довжина %1 + Impulse %1 Імпульс %1 + Octave %1 Октава %1 @@ -10001,90 +12627,112 @@ This chip was used in the Commodore 64 computer. vibedView + Volume: Гучність: + The 'V' knob sets the volume of the selected string. Регулятор 'V' встановлює гучність поточної струни. + String stiffness: Жорсткість: + The 'S' knob sets the stiffness of the selected string. The stiffness of the string affects how long the string will ring out. The lower the setting, the longer the string will ring. Регулятор 'S' встановлює жорсткість поточної струни. Цей параметр відповідає за тривалість звучання струни (чим більше значення жорсткості, тим довше дзвенить струна). + Pick position: Ударна позиція: + The 'P' knob sets the position where the selected string will be 'picked'. The lower the setting the closer the pick is to the bridge. Регулятор 'P' встановлює місце струни, де вона буде "притиснута". Чим нижче значення, тим ближче це місце буде до кобилки. + Pickup position: Положення звукознімача: + The 'PU' knob sets the position where the vibrations will be monitored for the selected string. The lower the setting, the closer the pickup is to the bridge. Регулятор 'PU' встановлює місце струни, звідки буде зніматися звук. Чим нижче значення, тим ближче це місце буде до мосту. + Pan: Бал: + The Pan knob determines the location of the selected string in the stereo field. Ця ручка встановлює стереобаланс для поточної струни. + Detune: Підлаштувати: + The Detune knob modifies the pitch of the selected string. Settings less than zero will cause the string to sound flat. Settings greater than zero will cause the string to sound sharp. Ручка підстроювання змінює зсув частоти для поточної струни. Від'ємні значення змусять струну звучати плоско, позитивні - гостро. + Fuzziness: Нечіткість: + The Slap knob adds a bit of fuzz to the selected string which is most apparent during the attack, though it can also be used to make the string sound more 'metallic'. Ця ручка додає розмитість звуку, що найбільш помітно під час наростання, втім, це може використовуватися, щоб зробити звук більш "металевим". + Length: Довжина: + The Length knob sets the length of the selected string. Longer strings will both ring longer and sound brighter, however, they will also eat up more CPU cycles. Ручка довжини встановлює довжину поточної струни. Чим довша струна, тим більш чистий і довгий звук вона дає; однак це вимагає більше ресурсів ЦП. + Impulse or initial state Початкова швидкість/початковий стан + The 'Imp' selector determines whether the waveform in the graph is to be treated as an impulse imparted to the string by the pick or the initial state of the string. Перемикач "Imp" встановлює режим роботи струни: якщо він включений, то зазначена форма сигналу інтерпретується як початковий імпульс, інакше - як початкова форма струни. + Octave Октава + The Octave selector is used to choose which harmonic of the note the string will ring at. For example, '-2' means the string will ring two octaves below the fundamental, 'F' means the string will ring at the fundamental, and '6' means the string will ring six octaves above the fundamental. Перемикач октав дозволяє вказати гармоніку основної частоти, на якій буде звучати струна. Наприклад, "-2" означає, що струна буде звучати двома октавами нижче основної частоти, "F" змусить струну дзвеніти на основній частоті інструменту, а "6" - на частоті, на шість октав більш високій, ніж основна. + Impulse Editor Редактор сигналу + The waveform editor provides control over the initial state or impulse that is used to start the string vibrating. The buttons to the right of the graph will initialize the waveform to the selected type. The '?' button will load a waveform from a file--only the first 128 samples will be loaded. The waveform can also be drawn in the graph. @@ -10102,6 +12750,7 @@ The 'N' button will normalize the waveform. Кнопка 'N' нормалізує рівень. + Vibed models up to nine independently vibrating strings. The 'String' selector allows you to choose which string is being edited. The 'Imp' selector chooses whether the graph represents an impulse or the initial state of the string. The 'Octave' selector chooses which harmonic the string should vibrate at. The graph allows you to control the initial state or impulse used to set the string in motion. @@ -10132,129 +12781,160 @@ The LED in the lower right corner of the waveform editor determines whether the Індикатор-перемикач зліва внизу визначає, чи включена поточна струна. + Enable waveform Включити сигнал + Click here to enable/disable waveform. Натисніть, щоб увімкнути/вимкнути сигнал. + String Струна + The String selector is used to choose which string the controls are editing. A Vibed instrument can contain up to nine independently vibrating strings. The LED in the lower right corner of the waveform editor indicates whether the selected string is active. Перемикач струн дозволяє вибрати струну, чиї властивості редагуються. Інструмент Vibed містить до дев'яти незалежно звучних струн, індикатор в лівому нижньому куті показує, активна чи поточна струна (тобто чи буде вона чутна). + Sine wave Синусоїда - Triangle wave - Трикутник - - - Saw wave - Зигзаг - - - Square wave - Квадратна хвиля - - - White noise wave - Білий шум - - - User defined wave - Користувацька - - - Smooth - Згладити - - - Click here to smooth waveform. - Клацніть щоб згладити форму сигналу. - - - Normalize - Нормалізувати - - - Click here to normalize waveform. - Натисніть, щоб нормалізувати сигнал. - - + Use a sine-wave for current oscillator. Генерувати гармонійний (синусоїдальний) сигнал. + + Triangle wave + Трикутник + + + Use a triangle-wave for current oscillator. Генерувати трикутний сигнал. + + Saw wave + Зигзаг + + + Use a saw-wave for current oscillator. Генерувати зигзагоподібний сигнал. + + Square wave + Квадратна хвиля + + + Use a square-wave for current oscillator. Генерувати квадрат. + + White noise wave + Білий шум + + + Use white-noise for current oscillator. Генерувати білий шум. + + User defined wave + Користувацька + + + Use a user-defined waveform for current oscillator. Задати форму сигналу. + + + Smooth + Згладити + + + + Click here to smooth waveform. + Клацніть щоб згладити форму сигналу. + + + + Normalize + Нормалізувати + + + + Click here to normalize waveform. + Натисніть, щоб нормалізувати сигнал. + voiceObject + Voice %1 pulse width Голос %1 довжина сигналу + Voice %1 attack Вступ %1-го голосу + Voice %1 decay Згасання %1-го голосу + Voice %1 sustain Витримка для %1-го голосу + Voice %1 release Зменшення %1-го голосу + Voice %1 coarse detuning Підналаштування %1-голосу (грубо) + Voice %1 wave shape Форма сигналу для %1-го голосу + Voice %1 sync Синхронізація %1-го голосу + Voice %1 ring modulate Голос %1 кільцевий модулятор + Voice %1 filtered Фільтрований %1-й голос + Voice %1 test Голос %1 тест @@ -10262,58 +12942,72 @@ The LED in the lower right corner of the waveform editor determines whether the waveShaperControlDialog + INPUT ВХІД + Input gain: Вхідне підсилення: + OUTPUT ВИХІД + Output gain: Вихідне підсилення: + Reset waveform Скидання сигналу + Click here to reset the wavegraph back to default Натисніть тут, щоб скинути граф хвилі назад за замовчуванням + Smooth waveform Згладжений сигнал + Click here to apply smoothing to wavegraph Натисніть тут, щоб застосувати згладжування графа хвилі + Increase graph amplitude by 1dB Збільште амплітуди графа хвилі на 1дБ + Click here to increase wavegraph amplitude by 1dB Натисніть тут, щоб збільшити амплітуду графа хвилі на 1дБ + Decrease graph amplitude by 1dB Зменшення амплітуди графа хвилі на 1дБ + Click here to decrease wavegraph amplitude by 1dB Натисніть тут, щоб зменшити амплітуду графа хвилі на 1дБ + Clip input Зрізати вхідний сигнал + Clip input signal to 0dB Зрізати вхідний сигнал до 0дБ @@ -10321,12 +13015,14 @@ The LED in the lower right corner of the waveform editor determines whether the waveShaperControls + Input gain Вхідне підсилення + Output gain Вихідне підсилення - \ No newline at end of file + diff --git a/data/locale/zh_TW.ts b/data/locale/zh_TW.ts index d2209539e..261d7c666 100644 --- a/data/locale/zh_TW.ts +++ b/data/locale/zh_TW.ts @@ -2,30 +2,62 @@ AboutDialog + About LMMS - 關於LMMS + 關於 LMMS + + LMMS + LMMS + + + Version %1 (%2/%3, Qt %4, %5) 版本 %1 (%2/%3, Qt %4, %5) + About 關於 + LMMS - easy music production for everyone LMMS - 人人都是作曲家 + + Copyright © %1 + 版權所有 © %1 + + + + <html><head/><body><p><a href="https://lmms.io"><span style=" text-decoration: underline; color:#0000ff;">https://lmms.io</span></a></p></body></html> + <html><head/><body><p><a href="https://lmms.io"><span style=" text-decoration: underline; color:#0000ff;">https://lmms.io</span></a></p></body></html> + + + Authors 作者 + + Involved + 參與者 + + + + Contributors ordered by number of commits: + 貢獻者名單(以提交次數排序): + + + Translation 翻譯 + Current language not translated (or native English). If you're interested in translating LMMS in another language or want to improve existing translations, you're welcome to help us! Simply contact the maintainer! @@ -42,61 +74,50 @@ BrLi <brli at chakraos.org> 若你有興趣提高翻譯品質,請聯絡維護團隊 (https://github.com/AOSC-Dev/translations)、之前的譯者或本項目維護者! + License 授權協議 - - LMMS - LMMS - - - Involved - 參與者 - - - Contributors ordered by number of commits: - 貢獻者名單(以提交次數排序): - - - Copyright © %1 - 版權所有 © %1 - - - <html><head/><body><p><a href="https://lmms.io"><span style=" text-decoration: underline; color:#0000ff;">https://lmms.io</span></a></p></body></html> - - AmplifierControlDialog + VOL VOL + Volume: 音量: + PAN PAN + Panning: 聲相: + LEFT + Left gain: 左增益: + RIGHT + Right gain: 右增益: @@ -104,18 +125,22 @@ BrLi <brli at chakraos.org> AmplifierControls + Volume 音量 + Panning 聲相 + Left gain 左增益 + Right gain 右增益 @@ -123,10 +148,12 @@ BrLi <brli at chakraos.org> AudioAlsaSetupWidget + DEVICE 裝置 + CHANNELS 聲道數 @@ -134,78 +161,98 @@ BrLi <brli at chakraos.org> AudioFileProcessorView + Open other sample 開啟其他取樣 + Click here, if you want to open another audio-file. A dialog will appear where you can select your file. Settings like looping-mode, start and end-points, amplify-value, and so on are not reset. So, it may not sound like the original sample. 如果想打開另一個音訊檔,請點擊這裡。接著會出現檔案選擇視窗。諸如循環模式 (looping-mode),起始/結束點,放大率 (amplify-value) 之類的值不會被重置。因此聽起來會和取樣來源有差異。 + Reverse sample 反轉取樣 + If you enable this button, the whole sample is reversed. This is useful for cool effects, e.g. a reversed crash. 如果點擊此按鈕,整個取樣將會被反轉。能用於製作很酷的效果,例如 reversed crash. - Amplify: - 放大: - - - With this knob you can set the amplify ratio. When you set a value of 100% your sample isn't changed. Otherwise it will be amplified up or down (your actual sample-file isn't touched!) - 此旋鈕用於調整放大比率。當設爲100% 時採樣不會變化。除此之外,不是放大就是減弱(原始的採樣文件不會被改變) - - - Startpoint: - 起始點: - - - Endpoint: - 終點: - - - Continue sample playback across notes - 跨音符繼續播放採樣 - - - Enabling this option makes the sample continue playing across different notes - if you change pitch, or the note length stops before the end of the sample, then the next note played will continue where it left off. To reset the playback to the start of the sample, insert a note at the bottom of the keyboard (< 20 Hz) - - - + Disable loop 停用循環 + This button disables looping. The sample plays only once from start to end. 點擊此按鈕可以禁止循環播放。取樣檔案將從頭到尾播放一次。 + + Enable loop 啟用循環 + This button enables forwards-looping. The sample loops between the end point and the loop point. 點擊此按鈕後,Forwards-looping 會被打開,採樣將在終止點(End Point)和循環點(Loop Point)之間播放。 + This button enables ping-pong-looping. The sample loops backwards and forwards between the end point and the loop point. 點擊此按鈕後,Ping-pong-looping 會被打開,採樣將在終止點 (End Point) 和循環點 (Loop Point) 之間來回播放。 + + Continue sample playback across notes + 跨音符繼續播放採樣 + + + + Enabling this option makes the sample continue playing across different notes - if you change pitch, or the note length stops before the end of the sample, then the next note played will continue where it left off. To reset the playback to the start of the sample, insert a note at the bottom of the keyboard (< 20 Hz) + + + + + Amplify: + 放大: + + + + With this knob you can set the amplify ratio. When you set a value of 100% your sample isn't changed. Otherwise it will be amplified up or down (your actual sample-file isn't touched!) + 此旋鈕用於調整放大比率。當設爲100% 時採樣不會變化。除此之外,不是放大就是減弱(原始的採樣文件不會被改變) + + + + Startpoint: + 起始點: + + + With this knob you can set the point where AudioFileProcessor should begin playing your sample. 調節此旋鈕,以告訴 AudioFileProcessor 在哪裏開始播放。 + + Endpoint: + 終點: + + + With this knob you can set the point where AudioFileProcessor should stop playing your sample. 調節此旋鈕,以告訴 AudioFileProcessor 在哪裏停止播放。 + Loopback point: 循環點: + With this knob you can set the point where the loop starts. 調節此旋鈕,以設置循環開始的地方。 @@ -213,6 +260,7 @@ BrLi <brli at chakraos.org> AudioFileProcessorWaveView + Sample length: 採樣長度: @@ -220,26 +268,32 @@ BrLi <brli at chakraos.org> AudioJack + JACK client restarted - JACK客戶端已重啓 + JACK 客戶端已重啓 + LMMS was kicked by JACK for some reason. Therefore the JACK backend of LMMS has been restarted. You will have to make manual connections again. - LMMS由於某些原因與JACK斷開連接,這可能是因爲LMMS的JACK後端重啓導致的,你需要手動重新連接。 + LMMS 由於某些原因與 JACK 中斷連線,因此 LMMS 的 JACK 後端已重新啟動,您必須手動重新連線。 + JACK server down - JACK服務崩潰 + JACK 伺服器發生問題 + The JACK server seems to have been shutdown and starting a new instance failed. Therefore LMMS is unable to proceed. You should save your project and restart JACK and LMMS. - JACK服務好像崩潰了而重開也失敗了,因此LMMS無法繼續執行。你需要儲存你的工作然後重啓JACK和LMMS。 + JACK 伺服器似乎發生問題,而且無法重新啟動,因此 LMMS 無法繼續執行。請儲存專案,然後重新啟動 JACK 和 LMMS。 + CLIENT-NAME 客戶端名稱 + CHANNELS 聲道數 @@ -247,10 +301,12 @@ BrLi <brli at chakraos.org> AudioOss::setupWidget + DEVICE - 設備 + 裝置 + CHANNELS 聲道數 @@ -258,21 +314,25 @@ BrLi <brli at chakraos.org> AudioPortAudio::setupWidget + BACKEND 後端 + DEVICE - 設備 + 裝置 AudioPulseAudio::setupWidget + DEVICE - 設備 + 裝置 + CHANNELS 聲道數 @@ -280,17 +340,20 @@ BrLi <brli at chakraos.org> AudioSdl::setupWidget + DEVICE - 設備 + 裝置 AudioSndio::setupWidget + DEVICE 裝置 + CHANNELS 聲道數 @@ -298,72 +361,88 @@ BrLi <brli at chakraos.org> AudioSoundIo::setupWidget + BACKEND 後端 + DEVICE - 設備 + 裝置 AutomatableModel + &Reset (%1%2) - 重置(%1%2)(&R) + 重設(%1%2)(&R) + &Copy value (%1%2) 複製值(%1%2)(&C) + &Paste value (%1%2) 貼上值(%1%2)(&P) + Edit song-global automation 編輯歌曲全局的自動控制裝置 - Connected to %1 - 連接到%1 - - - Connected to controller - 連接到控制器 - - - Edit connection... - 編輯連接... - - - Remove connection - 刪除連接 - - - Connect to controller... - 連接到控制器... - - + Remove song-global automation - 刪除歌曲全局的自動控制裝置 + 移除歌曲全域自動控制裝置 + Remove all linked controls - 刪除所有已連接的控制器 + 移除所有已連線的控制器 + + + + Connected to %1 + 已連線至 %1 + + + + Connected to controller + 連線至控制器 + + + + Edit connection... + 編輯連線… + + + + Remove connection + 移除連線 + + + + Connect to controller... + 連線至控制器… AutomationEditor + Please open an automation pattern with the context menu of a control! - 請使用控制的上下文菜單打開一個自動控制樣式! + 請透過控制的右鍵選單開啟自動控制模式! + Values copied 值已複製 + All selected values were copied to the clipboard. 所有選中的值已複製。 @@ -371,157 +450,192 @@ BrLi <brli at chakraos.org> AutomationEditorWindow + Play/pause current pattern (Space) 播放/暫停當前片段(空格) + Click here if you want to play the current pattern. This is useful while editing it. The pattern is automatically looped when the end is reached. 點擊這裏播放片段。編輯時很有用,片段會自動循環播放。 + Stop playing of current pattern (Space) 停止當前片段(空格) + Click here if you want to stop playing of the current pattern. 點擊這裏停止播放片段。 - Draw mode (Shift+D) - 繪製模式 (Shift+D) - - - Erase mode (Shift+E) - 擦除模式 (Shift+E) - - - Flip vertically - 垂直翻轉 - - - Flip horizontally - 水平翻轉 - - - Click here and the pattern will be inverted.The points are flipped in the y direction. - 點擊這裡來翻轉圖形 (pattern)。圖上的點會隨y軸翻轉。 - - - Click here and the pattern will be reversed. The points are flipped in the x direction. - 點擊這裡來翻轉圖形 (pattern)。圖上的點會隨x軸翻轉。 - - - Click here and draw-mode will be activated. In this mode you can add and move single values. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. - 點擊這裏啓用繪製模式。在此模式下你可以增加或移動單個值。 大部分時間下默認使用此模式。你也可以按鍵盤上的 ‘Shift+D’激活此模式。 - - - Click here and erase-mode will be activated. In this mode you can erase single values. You can also press 'Shift+E' on your keyboard to activate this mode. - 點擊啓用擦除模式。此模式下你可以擦除單個值。你可以按鍵盤上的 'Shift+E' 啓用此模式。 - - - Discrete progression - 區間進程 (Discrete progression) - - - Linear progression - 線性進程 (Linear progression) - - - Cubic Hermite progression - - - - Tension value for spline - - - - A higher tension value may make a smoother curve but overshoot some values. A low tension value will cause the slope of the curve to level off at each control point. - - - - Click here to choose discrete progressions for this automation pattern. The value of the connected object will remain constant between control points and be set immediately to the new value when each control point is reached. - - - - Click here to choose linear progressions for this automation pattern. The value of the connected object will change at a steady rate over time between control points to reach the correct value at each control point without a sudden change. - - - - Click here to choose cubic hermite progressions for this automation pattern. The value of the connected object will change in a smooth curve and ease in to the peaks and valleys. - - - - Cut selected values (%1+X) - 剪切選定值 (%1+X) - - - Copy selected values (%1+C) - 複製選定值 (%1+C) - - - Paste values from clipboard (%1+V) - 從剪貼簿貼上值 (%1+V) - - - Click here and selected values will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. - 點擊這裏,選擇的值將會被剪切到剪切板。你可以使用粘貼按鈕將它們粘貼到任意地方,存爲任意片段。 - - - Click here and selected values will be copied into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. - 點擊這裏,選擇的值將會被複制到剪切板。你可以使用粘貼按鈕將它們粘貼到任意地方,存爲任意片段。 - - - Click here and the values from the clipboard will be pasted at the first visible measure. - 點擊這裏,選擇的值將從剪貼板粘貼到第一個可見的小節。 - - - Tension: - - - - Automation Editor - no pattern - 自動控制編輯器 - 沒有片段 - - - Automation Editor - %1 - 自動控制編輯器 - %1 - - + Edit actions 編輯功能 + + Draw mode (Shift+D) + 繪製模式 (Shift+D) + + + + Erase mode (Shift+E) + 擦除模式 (Shift+E) + + + + Flip vertically + 垂直翻轉 + + + + Flip horizontally + 水平翻轉 + + + + Click here and the pattern will be inverted.The points are flipped in the y direction. + 點擊這裡來翻轉圖形 (pattern)。圖上的點會隨y軸翻轉。 + + + + Click here and the pattern will be reversed. The points are flipped in the x direction. + 點擊這裡來翻轉圖形 (pattern)。圖上的點會隨x軸翻轉。 + + + + Click here and draw-mode will be activated. In this mode you can add and move single values. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. + 點擊這裏啓用繪製模式。在此模式下你可以增加或移動單個值。 大部分時間下默認使用此模式。你也可以按鍵盤上的 ‘Shift+D’激活此模式。 + + + + Click here and erase-mode will be activated. In this mode you can erase single values. You can also press 'Shift+E' on your keyboard to activate this mode. + 點擊啓用擦除模式。此模式下你可以擦除單個值。你可以按鍵盤上的 'Shift+E' 啓用此模式。 + + + Interpolation controls 補間控制 - Timeline controls - 時間線控制 + + Discrete progression + 區間進程 (Discrete progression) + + Linear progression + 線性進程 (Linear progression) + + + + Cubic Hermite progression + + + + + Tension value for spline + + + + + A higher tension value may make a smoother curve but overshoot some values. A low tension value will cause the slope of the curve to level off at each control point. + + + + + Click here to choose discrete progressions for this automation pattern. The value of the connected object will remain constant between control points and be set immediately to the new value when each control point is reached. + + + + + Click here to choose linear progressions for this automation pattern. The value of the connected object will change at a steady rate over time between control points to reach the correct value at each control point without a sudden change. + + + + + Click here to choose cubic hermite progressions for this automation pattern. The value of the connected object will change in a smooth curve and ease in to the peaks and valleys. + + + + + Tension: + + + + + Cut selected values (%1+X) + 剪下選擇的值 (%1+X) + + + + Copy selected values (%1+C) + 複製選擇的值 (%1+C) + + + + Paste values from clipboard (%1+V) + 從剪貼簿貼上值 (%1+V) + + + + Click here and selected values will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. + 點擊這裏,選擇的值將會被剪切到剪切板。你可以使用粘貼按鈕將它們粘貼到任意地方,存爲任意片段。 + + + + Click here and selected values will be copied into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. + 點擊這裏,選擇的值將會被複制到剪切板。你可以使用粘貼按鈕將它們粘貼到任意地方,存爲任意片段。 + + + + Click here and the values from the clipboard will be pasted at the first visible measure. + 點擊這裏,選擇的值將從剪貼板粘貼到第一個可見的小節。 + + + Zoom controls 縮放控制 + Quantization controls - - - - Model is already connected to this pattern. - 模型已連接到此片段。 + 量化控制 + Quantization - + 量化 + Quantization. Sets the smallest step size for the Automation Point. By default this also sets the length, clearing out other points in the range. Press <Ctrl> to override this behaviour. + + + + Automation Editor - no pattern + 自動控制編輯器 - 沒有片段 + + + + + Automation Editor - %1 + 自動控制編輯器 - %1 + + + + Model is already connected to this pattern. + 模型已連接到此片段。 + AutomationPattern + Drag a control while pressing <%1> 按住<%1>拖動控制器 @@ -529,42 +643,57 @@ BrLi <brli at chakraos.org> AutomationPatternView + + double-click to open this pattern in automation editor + 雙擊在自動編輯器中打開此片段 + + + Open in Automation editor 在自動編輯器(Automation editor)中打開 + Clear 清除 + Reset name 重置名稱 + Change name 修改名稱 - %1 Connections - %1個連接 - - - Disconnect "%1" - 斷開“%1”的連接 - - + Set/clear record 設置/清除錄製 + Flip Vertically (Visible) 垂直翻轉 (可見) + Flip Horizontally (Visible) 水平翻轉 (可見) + + %1 Connections + %1個連接 + + + + Disconnect "%1" + 斷開“%1”的連接 + + + Model is already connected to this pattern. 模型已連接到此片段。 @@ -572,6 +701,7 @@ BrLi <brli at chakraos.org> AutomationTrack + Automation track 自動控制軌道 @@ -579,77 +709,95 @@ BrLi <brli at chakraos.org> BBEditor + Beat+Bassline Editor 節拍+低音線編輯器 + Play/pause current beat/bassline (Space) 播放/暫停當前節拍/低音線(空格) + Stop playback of current beat/bassline (Space) 停止播放當前節拍/低音線(空格) + Click here to play the current beat/bassline. The beat/bassline is automatically looped when its end is reached. 點擊這裏停止播放當前節拍/低音線。當結束時節拍/低音線會自動循環播放。 + Click here to stop playing of current beat/bassline. 點擊這裏停止播發當前節拍/低音線。 - Add beat/bassline - 添加節拍/低音線 - - - Add automation-track - 添加自動控制軌道 - - - Remove steps - 移除音階 - - - Add steps - 添加音階 - - + Beat selector 節拍選擇器 + Track and step actions - Clone Steps - + + Add beat/bassline + 添加節拍/低音線 + Add sample-track 新增採樣音軌 + + + Add automation-track + 添加自動控制軌道 + + + + Remove steps + 移除音階 + + + + Add steps + 添加音階 + + + + Clone Steps + + BBTCOView + Open in Beat+Bassline-Editor 在節拍+Bassline編輯器中打開 + Reset name 重置名稱 + Change name 修改名稱 + Change color 改變顏色 + Reset color to default 重置顏色 @@ -657,10 +805,12 @@ BrLi <brli at chakraos.org> BBTrack + Beat/Bassline %1 節拍/Bassline %1 + Clone of %1 %1 的副本 @@ -668,26 +818,32 @@ BrLi <brli at chakraos.org> BassBoosterControlDialog + FREQ 頻率 + Frequency: 頻率: + GAIN 增益 + Gain: 增益: + RATIO 比率 + Ratio: 比率: @@ -695,14 +851,17 @@ BrLi <brli at chakraos.org> BassBoosterControls + Frequency 頻率 + Gain 增益 + Ratio 比率 @@ -710,89 +869,111 @@ BrLi <brli at chakraos.org> BitcrushControlDialog + IN 輸入 + OUT 輸出 + + GAIN 增益 + Input Gain: 輸入增益: - Input Noise: - 輸入噪音: - - - Output Gain: - 輸出增益: - - - CLIP - 壓限 - - - Output Clip: - 輸出壓限: - - - Rate Enabled - - - - Enable samplerate-crushing - - - - Depth Enabled - 深度已啓用 - - - Enable bitdepth-crushing - - - - Sample rate: - 採樣率: - - - Stereo difference: - 雙聲道差異: - - - Levels: - 級別: - - + NOISE + + Input Noise: + 輸入噪音: + + + + Output Gain: + 輸出增益: + + + + CLIP + 壓限 + + + + Output Clip: + 輸出壓限: + + + + Rate Enabled + + + + + Enable samplerate-crushing + + + + + Depth Enabled + 深度已啓用 + + + + Enable bitdepth-crushing + + + + FREQ 頻率 + + Sample rate: + 採樣率: + + + STEREO + + Stereo difference: + 雙聲道差異: + + + QUANT + + + Levels: + 級別: + CaptionMenu + &Help 幫助(&H) + Help (not available) 幫助(不可用) @@ -800,10 +981,12 @@ BrLi <brli at chakraos.org> CarlaInstrumentView + Show GUI 顯示圖形界面 + Click here to show or hide the graphical user interface (GUI) of Carla. 點擊此處可以顯示或隱藏 Carla 的圖形界面。 @@ -811,6 +994,7 @@ BrLi <brli at chakraos.org> Controller + Controller %1 控制器%1 @@ -818,58 +1002,73 @@ BrLi <brli at chakraos.org> ControllerConnectionDialog + Connection Settings 連接設置 + MIDI CONTROLLER MIDI控制器 + Input channel 輸入通道 + CHANNEL 通道 + Input controller 輸入控制器 + CONTROLLER 控制器 + + Auto Detect 自動檢測 + MIDI-devices to receive MIDI-events from 用來接收 MIDI 事件的MIDI 設備 + USER CONTROLLER 用戶控制器 + MAPPING FUNCTION 映射函數 + OK 確定 + Cancel 取消 + LMMS LMMS + Cycle Detected. 檢測到環路。 @@ -877,18 +1076,22 @@ BrLi <brli at chakraos.org> ControllerRackView + Controller Rack 控制器機架 + Add 增加 + Confirm Delete 刪除前確認 + Confirm delete? There are existing connection(s) associated with this controller. There is no way to undo. 確定要刪除嗎?此控制器仍處於被連接狀態。此操作不可撤銷。 @@ -896,93 +1099,115 @@ BrLi <brli at chakraos.org> ControllerView + Controls 控制器 + Controllers are able to automate the value of a knob, slider, and other controls. 控制器可以自動控制旋鈕,滑塊和其他控件的值。 + Rename controller 重命名控制器 + Enter the new name for this controller 輸入這個控制器的新名稱 + + LFO + + + + &Remove this controller + Re&name this controller - - LFO - - CrossoverEQControlDialog + Band 1/2 Crossover: + Band 2/3 Crossover: + Band 3/4 Crossover: + Band 1 Gain: + Band 2 Gain: + Band 3 Gain: + Band 4 Gain: + Band 1 Mute + Mute Band 1 + Band 2 Mute + Mute Band 2 + Band 3 Mute + Mute Band 3 + Band 4 Mute + Mute Band 4 @@ -990,22 +1215,27 @@ BrLi <brli at chakraos.org> DelayControls + Delay Samples + Feedback + Lfo Frequency + Lfo Amount + Output gain 輸出增益 @@ -1013,228 +1243,311 @@ BrLi <brli at chakraos.org> DelayControlsDialog - Lfo Amt - - - - Delay Time - 延遲時間 - - - Feedback Amount - - - - Lfo - - - - Out Gain - - - - Gain - 增益 - - + DELAY + + Delay Time + 延遲時間 + + + FDBK + + Feedback Amount + + + + RATE + + Lfo + + + + AMNT + + + Lfo Amt + + + + + Out Gain + + + + + Gain + 增益 + DualFilterControlDialog - Filter 1 enabled - 已啓用過濾器 1 - - - Filter 2 enabled - 已啓用過濾器 2 - - - Click to enable/disable Filter 1 - 點擊啓用/禁用過濾器 1 - - - Click to enable/disable Filter 2 - 點擊啓用/禁用過濾器 2 - - + + FREQ 頻率 + + Cutoff frequency 切除頻率 + + RESO + + Resonance 共鳴 + + GAIN 增益 + + Gain 增益 + MIX + Mix 混合 + + + Filter 1 enabled + 已啓用過濾器 1 + + + + Filter 2 enabled + 已啓用過濾器 2 + + + + Click to enable/disable Filter 1 + 點擊啓用/禁用過濾器 1 + + + + Click to enable/disable Filter 2 + 點擊啓用/禁用過濾器 2 + DualFilterControls + Filter 1 enabled 過濾器1 已啓用 + Filter 1 type 過濾器 1 類型 + Cutoff 1 frequency 濾波器 1 截頻 + Q/Resonance 1 濾波器 1 Q值 + Gain 1 增益 1 + Mix 混合 + Filter 2 enabled 已啓用過濾器 2 + Filter 2 type 過濾器 1 類型 {2 ?} + Cutoff 2 frequency 濾波器 2 截頻 + Q/Resonance 2 濾波器 2 Q值 + Gain 2 增益 2 + + LowPass 低通 + + HiPass 高通 + + BandPass csg 帶通 csg + + BandPass czpg 帶通 czpg + + Notch 凹口濾波器 + + Allpass 全通 + + Moog Moog + + 2x LowPass 2 個低通串聯 + + RC LowPass 12dB RC 低通(12dB) + + RC BandPass 12dB RC 帶通(12dB) + + RC HighPass 12dB RC 高通(12dB) + + RC LowPass 24dB RC 低通(24dB) + + RC BandPass 24dB RC 帶通(24dB) + + RC HighPass 24dB RC 高通(24dB) + + Vocal Formant Filter 人聲移除過濾器 + + 2x Moog + + SV LowPass + + SV BandPass + + SV HighPass + + SV Notch + + Fast Formant + + Tripole @@ -1242,41 +1555,50 @@ BrLi <brli at chakraos.org> Editor + + Transport controls + + + + Play (Space) 播放(空格) + Stop (Space) 停止(空格) + Record 錄音 + Record while playing 播放時錄音 - - Transport controls - - Effect + Effect enabled 啓用效果器 + Wet/Dry mix 幹/溼混合 + Gate 門限 + Decay 衰減 @@ -1284,6 +1606,7 @@ BrLi <brli at chakraos.org> EffectChain + Effects enabled 啓用效果器 @@ -1291,10 +1614,12 @@ BrLi <brli at chakraos.org> EffectRackView + EFFECTS CHAIN 效果器鏈 + Add effect 增加效果器 @@ -1302,22 +1627,28 @@ BrLi <brli at chakraos.org> EffectSelectDialog + Add effect 增加效果器 + + Name 名稱 + Type 類型 + Description 描述 + Author @@ -1325,54 +1656,67 @@ BrLi <brli at chakraos.org> EffectView + Toggles the effect on or off. 打開或關閉效果. + On/Off 開/關 + W/D W/D + Wet Level: 效果度: + The Wet/Dry knob sets the ratio between the input signal and the effect signal that forms the output. 旋轉幹溼度旋鈕以調整原信號與有效果的信號的比例。 + DECAY 衰減 + Time: 時間: + The Decay knob controls how many buffers of silence must pass before the plugin stops processing. Smaller values will reduce the CPU overhead but run the risk of clipping the tail on delay and reverb effects. 衰減旋鈕控制在插件停止工作前,緩衝區中加入的靜音時常。較小的數值會降低CPU佔用率但是可能導致延遲或混響產生撕裂。 + GATE 門限 + Gate: 門限: + The Gate knob controls the signal level that is considered to be 'silence' while deciding when to stop processing signals. 門限旋鈕設置自動靜音時,被認爲是靜音的信號幅度。 + Controls 控制 + Effect plugins function as a chained series of effects where the signal will be processed from top to bottom. The On/Off switch allows you to bypass a given plugin at any point in time. @@ -1389,14 +1733,17 @@ Right clicking will bring up a context menu where you can change the order in wh + Move &up 向上移(&U) + Move &down 向下移(&D) + &Remove this plugin 移除此插件(&R) @@ -1404,58 +1751,72 @@ Right clicking will bring up a context menu where you can change the order in wh EnvelopeAndLfoParameters + Predelay 預延遲 + Attack 打進聲 + Hold 保持 + Decay 衰減 + Sustain 持續 + Release 釋放 + Modulation 調製 + LFO Predelay LFO 預延遲 + LFO Attack LFO 打進聲(attack) + LFO speed LFO 速度 + LFO Modulation LFO 調製 + LFO Wave Shape LFO 波形形狀 + Freq x 100 頻率 x 100 + Modulate Env-Amount 調製所有包絡 @@ -1463,349 +1824,439 @@ Right clicking will bring up a context menu where you can change the order in wh EnvelopeAndLfoView + + DEL DEL + Predelay: 預延遲: + Use this knob for setting predelay of the current envelope. The bigger this value the longer the time before start of actual envelope. 使用預延遲旋鈕設定此包絡的預延遲,較大的值會加長包絡開始的時間。 + + ATT ATT + Attack: 打進聲: + Use this knob for setting attack-time of the current envelope. The bigger this value the longer the envelope needs to increase to attack-level. Choose a small value for instruments like pianos and a big value for strings. 使用起音旋鈕設定此包絡的起音時間,較大的值會讓包絡達到起音值的時間增加。爲鋼琴等樂器選擇小值而絃樂選擇大值。 + HOLD 持續 + Hold: 持續: + Use this knob for setting hold-time of the current envelope. The bigger this value the longer the envelope holds attack-level before it begins to decrease to sustain-level. 使用持續旋鈕設定此包絡的持續時間。較大的值會在它衰減到持續值時,保持包絡在起音值更久。 + DEC 衰減 + Decay: 衰減: + Use this knob for setting decay-time of the current envelope. The bigger this value the longer the envelope needs to decrease from attack-level to sustain-level. Choose a small value for instruments like pianos. 使用衰減旋鈕設定此包絡的衰減值。較大的值會延長包絡從起音值衰減到持續值的時間。爲鋼琴等樂器選擇一個小值。 + SUST 持續 + Sustain: 持續: + Use this knob for setting sustain-level of the current envelope. The bigger this value the higher the level on which the envelope stays before going down to zero. 使用持續旋鈕設置此包絡的持續值,較大的值會增加釋放前,包絡在此保持的值。 + REL 釋音 + Release: 釋音: + Use this knob for setting release-time of the current envelope. The bigger this value the longer the envelope needs to decrease from sustain-level to zero. Choose a big value for soft instruments like strings. 使用釋音旋鈕設定此包絡的釋音時間,較大值會增加包絡衰減到零的時間。爲絃樂等樂器選擇一個大值。 + + AMT + + Modulation amount: 調製量: + Use this knob for setting modulation amount of the current envelope. The bigger this value the more the according size (e.g. volume or cutoff-frequency) will be influenced by this envelope. 使用調製量旋鈕設置LFO對此包絡的調製量,較大的值會對此包絡控制的值(如音量或截頻)影響更大。 + LFO predelay: LFO 預延遲: + Use this knob for setting predelay-time of the current LFO. The bigger this value the the time until the LFO starts to oscillate. + LFO- attack: + Use this knob for setting attack-time of the current LFO. The bigger this value the longer the LFO needs to increase its amplitude to maximum. + SPD + LFO speed: + Use this knob for setting speed of the current LFO. The bigger this value the faster the LFO oscillates and the faster will be your effect. + Use this knob for setting modulation amount of the current LFO. The bigger this value the more the selected size (e.g. volume or cutoff-frequency) will be influenced by this LFO. + Click here for a sine-wave. 點擊這裡使用正弦波。 + Click here for a triangle-wave. 點擊這裡使用三角波。 + Click here for a saw-wave for current. 點擊這裡使用鋸齒波。 + Click here for a square-wave. 點擊這裡使用方形波。 + Click here for a user-defined wave. Afterwards, drag an according sample-file onto the LFO graph. 點擊這裡使用自訂波形。之後請把所用波形的樣本檔案拖到LFO Graph上。 + + Click here for random wave. + 點擊這裡使用隨機波形。 + + + FREQ x 100 頻率 x 100 + Click here if the frequency of this LFO should be multiplied by 100. 點擊這裡把這個LFO的頻率乘以100。 + multiply LFO-frequency by 100 + MODULATE ENV-AMOUNT + Click here to make the envelope-amount controlled by this LFO. + control envelope-amount by this LFO + ms/LFO: + Hint 提示 + Drag a sample from somewhere and drop it in this window. 把樣本檔案拖到這個視窗上放開。 - - Click here for random wave. - 點擊這裡使用隨機波形。 - EqControls + Input gain 輸入增益 + Output gain 輸出增益 + Low shelf gain + Peak 1 gain + Peak 2 gain + Peak 3 gain + Peak 4 gain + High Shelf gain + HP res + Low Shelf res + Peak 1 BW + Peak 2 BW + Peak 3 BW + Peak 4 BW + High Shelf res + LP res + HP freq + Low Shelf freq + Peak 1 freq + Peak 2 freq + Peak 3 freq + Peak 4 freq + High shelf freq + LP freq + HP active + Low shelf active + Peak 1 active + Peak 2 active + Peak 3 active + Peak 4 active + High shelf active + LP active + LP 12 + LP 24 + LP 48 + HP 12 + HP 24 + HP 48 + low pass type + high pass type + Analyse IN + Analyse OUT @@ -1813,85 +2264,108 @@ Right clicking will bring up a context menu where you can change the order in wh EqControlsDialog + HP + Low Shelf + Peak 1 + Peak 2 + Peak 3 + Peak 4 + High Shelf + LP + In Gain + + + Gain 增益 + Out Gain + Bandwidth: + + Octave + + + + Resonance : + Frequency: 頻率: + lp grp + hp grp - - Octave - - EqHandle + Reso: + BW: + + Freq: @@ -1899,190 +2373,237 @@ Right clicking will bring up a context menu where you can change the order in wh ExportProjectDialog + Export project 導出工程 + Output 輸出 + File format: - 文件格式: + 檔案格式: + Samplerate: 採樣率: + 44100 Hz 44100 Hz + 48000 Hz 48000 Hz + 88200 Hz 88200 Hz + 96000 Hz 96000 Hz + 192000 Hz 192000 Hz - Bitrate: - 碼率: - - - 64 KBit/s - 64 KBit/s - - - 128 KBit/s - 128 KBit/s - - - 160 KBit/s - 160 KBit/s - - - 192 KBit/s - 192 KBit/s - - - 256 KBit/s - 256 KBit/s - - - 320 KBit/s - 320 KBit/s - - + Depth: 位深: + 16 Bit Integer 16 位整形 - 32 Bit Float - 32 位浮點型 - - - Quality settings - 質量設置 - - - Interpolation: - 補間: - - - Zero Order Hold - 零階保持 - - - Sinc Fastest - 最快 Sinc 補間 - - - Sinc Medium (recommended) - 中等 Sinc 補間 (推薦) - - - Sinc Best (very slow!) - 最佳 Sinc 補間 (很慢!) - - - Oversampling (use with care!): - 過採樣 (請謹慎使用!): - - - 1x (None) - 1x (無) - - - 2x - 2x - - - 4x - 4x - - - 8x - 8x - - - Start - 開始 - - - Cancel - 取消 - - - Export as loop (remove end silence) - 導出爲迴環loop(移除結尾的靜音) - - - Export between loop markers - 只導出迴環標記中間的部分 - - - Could not open file - 無法打開文件 - - - Export project to %1 - 導出項目到 %1 - - - Error - 錯誤 - - - Error while determining file-encoder device. Please try to choose a different output format. - 尋找文件編碼設備時出錯。請使用另外一種輸出格式。 - - - Rendering: %1% - 渲染中:%1% - - - Could not open file %1 for writing. -Please make sure you have write permission to the file and the directory containing the file and try again! - - - + 24 Bit Integer 24 位元整數 - Use variable bitrate - 使用可變位元率 + + 32 Bit Float + 32 位浮點型 + Stereo mode: + Stereo + Joint Stereo + Mono + + + Bitrate: + 碼率: + + + + 64 KBit/s + 64 KBit/s + + + + 128 KBit/s + 128 KBit/s + + + + 160 KBit/s + 160 KBit/s + + + + 192 KBit/s + 192 KBit/s + + + + 256 KBit/s + 256 KBit/s + + + + 320 KBit/s + 320 KBit/s + + + + Use variable bitrate + 使用可變位元率 + + + + Quality settings + 質量設置 + + + + Interpolation: + 補間: + + + + Zero Order Hold + 零階保持 + + + + Sinc Fastest + 最快 Sinc 補間 + + + + Sinc Medium (recommended) + 中等 Sinc 補間 (推薦) + + + + Sinc Best (very slow!) + 最佳 Sinc 補間 (很慢!) + + + + Oversampling (use with care!): + 過採樣 (請謹慎使用!): + + + + 1x (None) + 1x (無) + + + + 2x + 2x + + + + 4x + 4x + + + + 8x + 8x + + + + Export as loop (remove end silence) + 導出爲迴環loop(移除結尾的靜音) + + + + Export between loop markers + 只導出迴環標記中間的部分 + + + + Start + 開始 + + + + Cancel + 取消 + + + + Could not open file + 無法開啟檔案 + + + + Could not open file %1 for writing. +Please make sure you have write permission to the file and the directory containing the file and try again! + 無法開啟 %1 以進行寫入。 +請確認您有權限存取此檔案,以及包含此檔案的目錄後再試一次。 + + + + Export project to %1 + 導出項目到 %1 + + + + Error + 錯誤 + + + + Error while determining file-encoder device. Please try to choose a different output format. + 偵測檔案編碼裝置時發生錯誤。請嘗試使用其他輸出格式。 + + + + Rendering: %1% + 渲染中:%1% + Compression level: @@ -2146,6 +2667,8 @@ Please make sure you have write permission to the file and the directory contain Fader + + Please enter a new value between %1 and %2: 請輸入一個介於%1和%2之間的數值: @@ -2153,6 +2676,7 @@ Please make sure you have write permission to the file and the directory contain FileBrowser + Browser 瀏覽器 @@ -2168,65 +2692,80 @@ Please make sure you have write permission to the file and the directory contain FileBrowserTreeWidget + Send to active instrument-track 發送到活躍的樂器軌道 - Open in new instrument-track/B+B Editor - 在新樂器軌道/B+B 編輯器中打開 - - - Loading sample - 加載採樣中 - - - Please wait, loading sample for preview... - 請稍候,加載採樣中... - - - --- Factory files --- - ---軟件自帶文件--- - - + Open in new instrument-track/Song Editor 在新的樂器軌道/歌曲編輯器中打開 + + Open in new instrument-track/B+B Editor + 在新樂器軌道/B+B 編輯器中打開 + + + + Loading sample + 加載採樣中 + + + + Please wait, loading sample for preview... + 請稍候,加載採樣中... + + + Error 錯誤 + does not appear to be a valid 並不是一個有效的 + file - 文件 + 檔案 + + + + --- Factory files --- + --- 內建檔案 --- FlangerControls + Delay Samples + Lfo Frequency + Seconds + Regen + Noise 噪音 + Invert 反轉 @@ -2234,57 +2773,70 @@ Please make sure you have write permission to the file and the directory contain FlangerControlsDialog - Delay Time: - 延遲時間: - - - Feedback Amount: - - - - White Noise Amount: - 白噪音數量: - - + DELAY + + Delay Time: + 延遲時間: + + + RATE + + Period: + + + + AMNT + Amount: + FDBK + + Feedback Amount: + + + + NOISE - Invert - 反轉 + + White Noise Amount: + 白噪音數量: - Period: - + + Invert + 反轉 FxLine + Channel send amount 通道發送的數量 + The FX channel receives input from one or more instrument tracks. It in turn can be routed to multiple other FX channels. LMMS automatically takes care of preventing infinite loops for you and doesn't allow making a connection that would result in an infinite loop. @@ -2295,22 +2847,27 @@ You can remove and move FX channels in the context menu, which is accessed by ri + Move &left 向左移(&L) + Move &right 向右移(&R) + Rename &channel 重命名通道(&C) + R&emove channel 刪除通道(&E) + Remove &unused channels 移除所有未用通道(&U) @@ -2318,22 +2875,29 @@ You can remove and move FX channels in the context menu, which is accessed by ri FxMixer + Master 主控 + + + FX %1 FX %1 + Volume 音量 + Mute 靜音 + Solo 獨奏 @@ -2341,26 +2905,32 @@ You can remove and move FX channels in the context menu, which is accessed by ri FxMixerView + FX-Mixer 效果混合器 + FX Fader %1 FX 衰減器 %1 + Mute 靜音 + Mute this FX channel 靜音此效果通道 + Solo 獨奏 + Solo FX channel 獨奏效果通道 @@ -2368,6 +2938,8 @@ You can remove and move FX channels in the context menu, which is accessed by ri FxRoute + + Amount to send from channel %1 to channel %2 從通道 %1 發送到通道 %2 的量 @@ -2375,14 +2947,17 @@ You can remove and move FX channels in the context menu, which is accessed by ri GigInstrument + Bank + Patch 音色 + Gain 增益 @@ -2390,740 +2965,926 @@ You can remove and move FX channels in the context menu, which is accessed by ri GigInstrumentView + Open other GIG file 打開另外的 GIG 文件 + Click here to open another GIG file 點擊這裏打開另外一個 GIG 文件 + Choose the patch 選擇路徑 + Click here to change which patch of the GIG file to use 點擊這裏選擇另一種 GIG 音色 + + Change which instrument of the GIG file is being played 更換正在使用的 GIG 文件中的樂器 + Which GIG file is currently being used 哪一個 GIG 文件正在被使用 + Which patch of the GIG file is currently being used GIG 文件的哪一個音色正在被使用 + Gain 增益 + Factor to multiply samples by + Open GIG file - 打開 GIG 文件 + 開啟 GIG 檔案 + GIG Files (*.gig) - GIG 文件 (*.gig) + GIG 檔案 (*.gig) GuiApplication + Working directory 工作目錄 + The LMMS working directory %1 does not exist. Create it now? You can change the directory later via Edit -> Settings. LMMS工作目錄%1不存在,現在新建一個嗎?你可以稍後在 編輯 -> 設置 中更改此設置。 + Preparing UI 正在準備界面 + Preparing song editor 正在準備歌曲編輯器 + Preparing mixer 正在準備混音器 + Preparing controller rack 正在準備控制機架 + Preparing project notes - 正在準備工程註釋 + 正在準備專案音符 + Preparing beat/bassline editor 正在準備節拍/低音線編輯器 + Preparing piano roll - 正在準備鋼琴窗 + 正在準備鋼琴捲簾 + Preparing automation editor - 正在準備自動編輯器 + 正在準備自動化控制編輯器 InstrumentFunctionArpeggio + Arpeggio + Arpeggio type + Arpeggio range - Arpeggio time + + Cycle steps - Arpeggio gate - - - - Arpeggio direction - - - - Arpeggio mode - - - - Up - 向上 - - - Down - 向下 - - - Up and down - 上和下 - - - Random - 隨機 - - - Free - 自由 - - - Sort - 排序 - - - Sync - 同步 - - - Down and up - 下和上 - - + Skip rate + Miss rate - Cycle steps + + Arpeggio time + + + Arpeggio gate + + + + + Arpeggio direction + + + + + Arpeggio mode + + + + + Up + 向上 + + + + Down + 向下 + + + + Up and down + 上和下 + + + + Down and up + 下和上 + + + + Random + 隨機 + + + + Free + 自由 + + + + Sort + 排序 + + + + Sync + 同步 + InstrumentFunctionArpeggioView + ARPEGGIO 琶音 + An arpeggio is a method playing (especially plucked) instruments, which makes the music much livelier. The strings of such instruments (e.g. harps) are plucked like chords. The only difference is that this is done in a sequential order, so the notes are not played at the same time. Typical arpeggios are major or minor triads, but there are a lot of other possible chords, you can select. + RANGE 範圍 + Arpeggio range: + octave(s) + Use this knob for setting the arpeggio range in octaves. The selected arpeggio will be played within specified number of octaves. - TIME - 時長 - - - Arpeggio time: - - - - ms - 毫秒 - - - Use this knob for setting the arpeggio time in milliseconds. The arpeggio time specifies how long each arpeggio-tone should be played. - - - - GATE - 門限 - - - Arpeggio gate: - - - - % - % - - - Use this knob for setting the arpeggio gate. The arpeggio gate specifies the percent of a whole arpeggio-tone that should be played. With this you can make cool staccato arpeggios. - - - - Chord: - 和絃: - - - Direction: - 方向: - - - Mode: - 模式: - - - SKIP - - - - Skip rate: - - - - The skip function will make the arpeggiator pause one step randomly. From its start in full counter clockwise position and no effect it will gradually progress to full amnesia at maximum setting. - - - - MISS - - - - Miss rate: - - - - The miss function will make the arpeggiator miss the intended note. - - - + CYCLE + Cycle notes: + note(s) + Jumps over n steps in the arpeggio and cycles around if we're over the note range. If the total note range is evenly divisible by the number of steps jumped over you will get stuck in a shorter arpeggio or even on one note. + + + SKIP + + + + + Skip rate: + + + + + + + % + % + + + + The skip function will make the arpeggiator pause one step randomly. From its start in full counter clockwise position and no effect it will gradually progress to full amnesia at maximum setting. + + + + + MISS + + + + + Miss rate: + + + + + The miss function will make the arpeggiator miss the intended note. + + + + + TIME + 時長 + + + + Arpeggio time: + + + + + ms + 毫秒 + + + + Use this knob for setting the arpeggio time in milliseconds. The arpeggio time specifies how long each arpeggio-tone should be played. + + + + + GATE + 門限 + + + + Arpeggio gate: + + + + + Use this knob for setting the arpeggio gate. The arpeggio gate specifies the percent of a whole arpeggio-tone that should be played. With this you can make cool staccato arpeggios. + + + + + Chord: + 和絃: + + + + Direction: + 方向: + + + + Mode: + 模式: + InstrumentFunctionNoteStacking + octave octave + + Major Major + Majb5 Majb5 + minor minor + minb5 minb5 + sus2 sus2 + sus4 sus4 + aug aug + augsus4 augsus4 + tri tri + 6 6 + 6sus4 6sus4 + 6add9 6add9 + m6 m6 + m6add9 m6add9 + 7 7 + 7sus4 7sus4 + 7#5 7#5 + 7b5 7b5 + 7#9 7#9 + 7b9 7b9 + 7#5#9 7#5#9 + 7#5b9 7#5b9 + 7b5b9 7b5b9 + 7add11 7add11 + 7add13 7add13 + 7#11 7#11 + Maj7 Maj7 + Maj7b5 Maj7b5 + Maj7#5 Maj7#5 + Maj7#11 Maj7#11 + Maj7add13 Maj7add13 + m7 m7 + m7b5 m7b5 + m7b9 m7b9 + m7add11 m7add11 + m7add13 m7add13 + m-Maj7 m-Maj7 + m-Maj7add11 m-Maj7add11 + m-Maj7add13 m-Maj7add13 + 9 9 + 9sus4 9sus4 + add9 add9 + 9#5 9#5 + 9b5 9b5 + 9#11 9#11 + 9b13 9b13 + Maj9 Maj9 + Maj9sus4 Maj9sus4 + Maj9#5 Maj9#5 + Maj9#11 Maj9#11 + m9 m9 + madd9 madd9 + m9b5 m9b5 + m9-Maj7 m9-Maj7 + 11 11 + 11b9 11b9 + Maj11 Maj11 + m11 m11 + m-Maj11 m-Maj11 + 13 13 + 13#9 13#9 + 13b9 13b9 + 13b5b9 13b5b9 + Maj13 Maj13 + m13 m13 + m-Maj13 m-Maj13 + Harmonic minor Harmonic minor + Melodic minor Melodic minor + Whole tone + Diminished Diminished + Major pentatonic Major pentatonic + Minor pentatonic Minor pentatonic + Jap in sen Jap in sen + Major bebop Major bebop + Dominant bebop Dominant bebop + Blues Blues + Arabic Arabic + Enigmatic Enigmatic + Neopolitan Neopolitan + Neopolitan minor Neopolitan minor + Hungarian minor Hungarian minor + Dorian Dorian - Phrygolydian + + Phrygian + Lydian Lydian + Mixolydian Mixolydian + Aeolian Aeolian + Locrian Locrian - Chords - Chords - - - Chord type - Chord type - - - Chord range - Chord range - - + Minor Minor + Chromatic Chromatic + Half-Whole Diminished + 5 5 + Phrygian dominant + Persian + + + Chords + Chords + + + + Chord type + Chord type + + + + Chord range + Chord range + InstrumentFunctionNoteStackingView - RANGE - 範圍 - - - Chord range: - 和絃範圍: - - - octave(s) - - - - Use this knob for setting the chord range in octaves. The selected chord will be played within specified number of octaves. - - - + STACKING 堆疊 + Chord: 和絃: + + + RANGE + 範圍 + + + + Chord range: + 和絃範圍: + + + + octave(s) + + + + + Use this knob for setting the chord range in octaves. The selected chord will be played within specified number of octaves. + + InstrumentMidiIOView + ENABLE MIDI INPUT 啓用MIDI輸入 + + CHANNEL 通道 + + VELOCITY 力度 + ENABLE MIDI OUTPUT 啓用MIDI輸出 + PROGRAM 樂器 - MIDI devices to receive MIDI events from - 用於接收 MIDI 事件的 MIDI 設備 - - - MIDI devices to send MIDI events to - 用於發送 MIDI 事件的 MIDI 設備 - - + NOTE 音符 + + MIDI devices to receive MIDI events from + 用於接收 MIDI 事件的 MIDI 設備 + + + + MIDI devices to send MIDI events to + 用於發送 MIDI 事件的 MIDI 設備 + + + CUSTOM BASE VELOCITY 自定義基準力度 + Specify the velocity normalization base for MIDI-based instruments at 100% note velocity + BASE VELOCITY 基準力度 @@ -3131,10 +3892,12 @@ You can remove and move FX channels in the context menu, which is accessed by ri InstrumentMiscView + MASTER PITCH 主音高 + Enables the use of Master Pitch 啓用主音高 @@ -3142,126 +3905,158 @@ You can remove and move FX channels in the context menu, which is accessed by ri InstrumentSoundShaping + VOLUME 音量 + Volume 音量 + CUTOFF 切除 + + Cutoff frequency 切除頻率 + RESO + Resonance 共鳴 + Envelopes/LFOs 壓限/低頻振盪 + Filter type 過濾器類型 + Q/Resonance + LowPass 低通 + HiPass 高通 + BandPass csg 帶通 csg + BandPass czpg 帶通 czpg + Notch 凹口濾波器 + Allpass 全通 + Moog Moog + 2x LowPass 2 個低通串聯 + RC LowPass 12dB RC 低通(12dB) + RC BandPass 12dB RC 帶通(12dB) + RC HighPass 12dB RC 高通(12dB) + RC LowPass 24dB RC 低通(24dB) + RC BandPass 24dB RC 帶通(24dB) + RC HighPass 24dB RC 高通(24dB) + Vocal Formant Filter 人聲移除過濾器 + 2x Moog + SV LowPass + SV BandPass + SV HighPass + SV Notch + Fast Formant + Tripole @@ -3269,50 +4064,62 @@ You can remove and move FX channels in the context menu, which is accessed by ri InstrumentSoundShapingView + TARGET 目標 + These tabs contain envelopes. They're very important for modifying a sound, in that they are almost always necessary for substractive synthesis. For example if you have a volume envelope, you can set when the sound should have a specific volume. If you want to create some soft strings then your sound has to fade in and out very softly. This can be done by setting large attack and release times. It's the same for other envelope targets like panning, cutoff frequency for the used filter and so on. Just monkey around with it! You can really make cool sounds out of a saw-wave with just some envelopes...! + FILTER + Here you can select the built-in filter you want to use for this instrument-track. Filters are very important for changing the characteristics of a sound. - Hz - Hz - - - Use this knob for setting the cutoff frequency for the selected filter. The cutoff frequency specifies the frequency for cutting the signal by a filter. For example a lowpass-filter cuts all frequencies above the cutoff frequency. A highpass-filter cuts all frequencies below cutoff frequency, and so on... - - - - RESO - - - - Resonance: - 共鳴: - - - Use this knob for setting Q/Resonance for the selected filter. Q/Resonance tells the filter how much it should amplify frequencies near Cutoff-frequency. - - - + FREQ 頻率 + cutoff frequency: + + Hz + Hz + + + + Use this knob for setting the cutoff frequency for the selected filter. The cutoff frequency specifies the frequency for cutting the signal by a filter. For example a lowpass-filter cuts all frequencies above the cutoff frequency. A highpass-filter cuts all frequencies below cutoff frequency, and so on... + + + + + RESO + + + + + Resonance: + 共鳴: + + + + Use this knob for setting Q/Resonance for the selected filter. Q/Resonance tells the filter how much it should amplify frequencies near Cutoff-frequency. + + + + Envelopes, LFOs and filters are not supported by the current instrument. 包絡和低頻振盪 (LFO) 不被當前樂器支持。 @@ -3320,85 +4127,107 @@ You can remove and move FX channels in the context menu, which is accessed by ri InstrumentTrack - unnamed_track - 未命名軌道 - - - Volume - 音量 - - - Panning - 聲相 - - - Pitch - 音高 - - - FX channel - 效果通道 - - - Default preset - 預置 - - + With this knob you can set the volume of the opened channel. 使用此旋鈕可以設置開放通道的音量。 + + + unnamed_track + 未命名軌道 + + + Base note 基本音 + + Volume + 音量 + + + + Panning + 聲相 + + + + Pitch + 音高 + + + Pitch range 音域範圍 + + FX channel + 效果通道 + + + Master Pitch 主音高 + + + + Default preset + 預置 + InstrumentTrackView + Volume 音量 + Volume: 音量: + VOL VOL + Panning 聲相 + Panning: 聲相: + PAN PAN + MIDI MIDI + Input 輸入 + Output 輸出 + FX %1: %2 效果 %1: %2 @@ -3406,110 +4235,137 @@ You can remove and move FX channels in the context menu, which is accessed by ri InstrumentTrackWindow + GENERAL SETTINGS 常規設置 - Instrument volume - 樂器音量 - - - Volume: - 音量: - - - VOL - VOL - - - Panning - 聲相 - - - Panning: - 聲相: - - - PAN - PAN - - - Pitch - 音高 - - - Pitch: - 音高: - - - cents - 音分 cents - - - PITCH - - - - FX channel - 效果通道 - - - FX - 效果 - - - Save preset - 保存預置 - - - XML preset file (*.xpf) - XML 預設文件 (*.xpf) - - - Pitch range (semitones) - 音域範圍(半音) - - - RANGE - 範圍 - - - Save current instrument track settings in a preset file - 保存當前樂器軌道設置到預設文件 - - - Click here, if you want to save current instrument track settings in a preset file. Later you can load this preset by double-clicking it in the preset-browser. - 如果你想保存當前樂器軌道設置到預設文件, 請點擊這裏。稍後你可以在預設瀏覽器中雙擊以使用它。 - - + Use these controls to view and edit the next/previous track in the song editor. 使用這些控制選項來查看和編輯在歌曲編輯器中的上個/下個軌道。 + + Instrument volume + 樂器音量 + + + + Volume: + 音量: + + + + VOL + VOL + + + + Panning + 聲相 + + + + Panning: + 聲相: + + + + PAN + PAN + + + + Pitch + 音高 + + + + Pitch: + 音高: + + + + cents + 音分 cents + + + + PITCH + + + + + Pitch range (semitones) + 音域範圍(半音) + + + + RANGE + 範圍 + + + + FX channel + 效果通道 + + + + FX + 效果 + + + + Save current instrument track settings in a preset file + 儲存目前的樂器軌道設定為預設集檔案 + + + + Click here, if you want to save current instrument track settings in a preset file. Later you can load this preset by double-clicking it in the preset-browser. + 如果你想保存當前樂器軌道設置到預設文件, 請點擊這裏。稍後你可以在預設瀏覽器中雙擊以使用它。 + + + SAVE 保存 + Envelope, filter & LFO + Chord stacking & arpeggio + Effects + MIDI settings MIDI設置 + Miscellaneous + + Save preset + 保存預置 + + + + XML preset file (*.xpf) + XML 預設集檔案 (*.xpf) + + + Plugin @@ -3517,25 +4373,30 @@ You can remove and move FX channels in the context menu, which is accessed by ri Knob + Set linear 設置爲線性 + Set logarithmic 設置爲對數 - Please enter a new value between %1 and %2: - 請輸入一個介於%1和%2之間的數值: - - + Please enter a new value between -96.0 dBFS and 6.0 dBFS: + + + Please enter a new value between %1 and %2: + 請輸入一個介於%1和%2之間的數值: + LadspaControl + Link channels 關聯通道 @@ -3543,10 +4404,12 @@ You can remove and move FX channels in the context menu, which is accessed by ri LadspaControlDialog + Link Channels 連接通道 + Channel 通道 @@ -3554,14 +4417,17 @@ You can remove and move FX channels in the context menu, which is accessed by ri LadspaControlView + Link channels 連接通道 + Value: 值: + Sorry, no help available. 啊哦,這個沒有幫助文檔。 @@ -3569,6 +4435,7 @@ You can remove and move FX channels in the context menu, which is accessed by ri LadspaEffect + Unknown LADSPA plugin %1 requested. 已請求未知 LADSPA 插件 %1. @@ -3576,6 +4443,7 @@ You can remove and move FX channels in the context menu, which is accessed by ri LcdSpinBox + Please enter a new value between %1 and %2: 請輸入一個介於%1和%2之間的數值: @@ -3583,18 +4451,26 @@ You can remove and move FX channels in the context menu, which is accessed by ri LeftRightNav + + + Previous 上個 + + + Next 下個 + Previous (%1) 上 (%1) + Next (%1) 下 (%1) @@ -3602,30 +4478,37 @@ You can remove and move FX channels in the context menu, which is accessed by ri LfoController + LFO Controller LFO 控制器 + Base value 基準值 + Oscillator speed 振動速度 + Oscillator amount + Oscillator phase + Oscillator waveform 振動波形 + Frequency Multiplier @@ -3633,114 +4516,141 @@ You can remove and move FX channels in the context menu, which is accessed by ri LfoControllerDialog + LFO + LFO Controller LFO 控制器 + BASE 基準 + Base amount: 基礎值: + todo + SPD + LFO-speed: + Use this knob for setting speed of the LFO. The bigger this value the faster the LFO oscillates and the faster the effect. + + AMNT + + + + Modulation amount: 調製量: + Use this knob for setting modulation amount of the LFO. The bigger this value, the more the connected control (e.g. volume or cutoff-frequency) will be influenced by the LFO. + PHS + Phase offset: + degrees + With this knob you can set the phase offset of the LFO. That means you can move the point within an oscillation where the oscillator begins to oscillate. For example if you have a sine-wave and have a phase-offset of 180 degrees the wave will first go down. It's the same with a square-wave. + Click here for a sine-wave. 點擊這裡使用正弦波。 + Click here for a triangle-wave. 點擊這裡使用三角波。 + Click here for a saw-wave. + Click here for a square-wave. 點擊這裡使用方形波。 - Click here for an exponential wave. - - - - Click here for white-noise. - - - - Click here for a user-defined shape. -Double click to pick a file. - - - + Click here for a moog saw-wave. - AMNT + + Click here for an exponential wave. + + + + + Click here for white-noise. + + + + + Click here for a user-defined shape. +Double click to pick a file. LmmsCore + Generating wavetables 正在生成波形表 + Initializing data structures 正在初始化數據結構 + Opening audio and midi devices 正在啓動音頻和 MIDI 設備 + Launching mixer threads 生在啓動混音器線程 @@ -3748,396 +4658,500 @@ Double click to pick a file. MainWindow + + Configuration file + 設定檔 + + + + Error while parsing configuration file at line %1:%2: %3 + 解析設定檔時發生錯誤(行 %1:%2:%3) + + + + Could not open file + 無法開啟檔案 + + + + Could not open file %1 for writing. +Please make sure you have write permission to the file and the directory containing the file and try again! + 無法開啟 %1 以進行寫入。 +請確認您有權限存取此檔案,以及包含此檔案的目錄後再試一次。 + + + + Project recovery + 工程恢復 + + + + There is a recovery file present. It looks like the last session did not end properly or another instance of LMMS is already running. Do you want to recover the project of this session? + 發現復原檔案。可能是上一個工作階段未正常結束,或者另一個 LMMS 已在執行。您想要復原這個專案嗎? + + + + + + Recover + 恢復 + + + + Recover the file. Please don't run multiple instances of LMMS when you do this. + 復原檔案。請不要在復原檔案時同時開啟多個 LMMS 視窗。 + + + + + + Discard + 丟棄 + + + + Launch a default session and delete the restored files. This is not reversible. + 開啟新的預設工作階段並刪除已復原的檔案。此操作無法復原。 + + + + Version %1 + 版本 %1 + + + + Preparing plugin browser + 正在準備插件瀏覽器 + + + + Preparing file browsers + 正在準備檔案瀏覽器 + + + + My Projects + 我的工程 + + + + My Samples + 我的採樣 + + + + My Presets + 我的預設 + + + + My Home + 我的主目錄 + + + + Root directory + 根目錄 + + + + Volumes + 音量 + + + + My Computer + 我的電腦 + + + + Loading background artwork + 正在加載背景圖案 + + + + &File + 檔案(&F) + + + &New 新建(&N) + + New from template + 從模版新建工程 + + + &Open... 打開(&O)... + + &Recently Opened Projects + 最近打開的工程(&R) + + + &Save 保存(&S) + Save &As... 另存爲(&A)... + + Save as New &Version + 保存爲新版本(&V) + + + + Save as default template + 保存爲默認模板 + + + Import... 導入... + E&xport... 導出(&E)... + + E&xport Tracks... + 導出音軌(&X)... + + + + Export &MIDI... + 導出 MIDI (&M)... + + + &Quit 退出(&Q) + &Edit 編輯(&E) + + Undo + 撤銷 + + + + Redo + 重做 + + + Settings 設置 + + &View + 視圖 (&V) + + + &Tools 工具(&T) + &Help 幫助(&H) + + Online Help + 在線幫助 + + + Help 幫助 - What's this? - 這是什麼? + + What's This? + 這是什麼? + About 關於 + Create new project 新建工程 + Create new project from template 從模版新建工程 + Open existing project 打開已有工程 + Recently opened projects 最近打開的工程 + Save current project 保存當前工程 + Export current project 導出當前工程 - Song Editor + + What's this? + 這是什麼? + + + + Toggle metronome + 開啓/關閉節拍器 + + + + Show/hide Song-Editor 顯示/隱藏歌曲編輯器 + By pressing this button, you can show or hide the Song-Editor. With the help of the Song-Editor you can edit song-playlist and specify when which track should be played. You can also insert and move samples (e.g. rap samples) directly into the playlist. 點擊這個按鈕, 你可以顯示/隱藏歌曲編輯器。在歌曲編輯器的幫助下, 你可以編輯歌曲播放列表並且設置哪個音軌在哪個時間播放。你還可以在播放列表中直接插入和移動採樣(如 RAP 採樣)。 - Beat+Bassline Editor + + Show/hide Beat+Bassline Editor 顯示/隱藏節拍+旋律編輯器 + By pressing this button, you can show or hide the Beat+Bassline Editor. The Beat+Bassline Editor is needed for creating beats, and for opening, adding, and removing channels, and for cutting, copying and pasting beat and bassline-patterns, and for other things like that. - Piano Roll + + Show/hide Piano-Roll 顯示/隱藏鋼琴窗 + Click here to show or hide the Piano-Roll. With the help of the Piano-Roll you can edit melodies in an easy way. 點擊這裏顯示或隱藏鋼琴窗。在鋼琴窗的幫助下, 你可以很容易地編輯旋律。 - Automation Editor + + Show/hide Automation Editor 顯示/隱藏自動控制編輯器 + Click here to show or hide the Automation Editor. With the help of the Automation Editor you can edit dynamic values in an easy way. 點擊這裏顯示或隱藏自動控制編輯器。在自動控制編輯器的幫助下, 你可以很簡單地控制動態數值。 - FX Mixer + + Show/hide FX Mixer 顯示/隱藏混音器 + Click here to show or hide the FX Mixer. The FX Mixer is a very powerful tool for managing effects for your song. You can insert effects into different effect-channels. 點擊這裏顯示或隱藏 FX 混音器。FX 混音器是管理你歌曲中不同音效的強大工具。你可以向不同的通道添加不同的效果。 - Project Notes + + Show/hide project notes 顯示/隱藏工程註釋 + Click here to show or hide the project notes window. In this window you can put down your project notes. 點擊這裏顯示或隱藏工程註釋窗。在此窗口中你可以寫下工程的註釋。 - Controller Rack + + Show/hide controller rack 顯示/隱藏控制器機架 + Untitled - 未標題 + 未命名 + + Recover session. Please save your work! + 恢復會話。請保存你的工作! + + + LMMS %1 LMMS %1 + + Recovered project not saved + 恢復的工程沒有保存 + + + + This project was recovered from the previous session. It is currently unsaved and will be lost if you don't save it. Do you want to save it now? + 這個工程已從上一個會話中恢復。它現在沒有被保存, 並且如果你不保存, 它將會丟失。你現在想保存它嗎? + + + Project not saved 工程未保存 + The current project was modified since last saving. Do you want to save it now? 此工程自上次保存後有了修改,你想保存嗎? + + Open Project + 打開工程 + + + + LMMS (*.mmp *.mmpz) + LMMS (*.mmp *.mmpz) + + + + Save Project + 保存工程 + + + + LMMS Project + LMMS 工程 + + + + LMMS Project Template + LMMS 工程模板 + + + + Save project template + + + + + Overwrite default template? + 覆蓋默認的模板? + + + + This will overwrite your current default template. + 這將會覆蓋你的當前默認模板。 + + + Help not available 幫助不可用 + Currently there's no help available in LMMS. Please visit http://lmms.sf.net/wiki for documentation on LMMS. LMMS現在沒有可用的幫助 請訪問 http://lmms.sf.net/wiki 瞭解LMMS的相關文檔。 - LMMS (*.mmp *.mmpz) - LMMS (*.mmp *.mmpz) - - - Version %1 - 版本 %1 - - - Configuration file - 配置文件 - - - Error while parsing configuration file at line %1:%2: %3 - 解析配置文件發生錯誤(行%1:%2:%3) - - - Volumes - 音量 - - - Undo - 撤銷 - - - Redo - 重做 - - - My Projects - 我的工程 - - - My Samples - 我的採樣 - - - My Presets - 我的預設 - - - My Home - 我的主目錄 - - - My Computer - 我的電腦 - - - &File - 文件(&F) - - - &Recently Opened Projects - 最近打開的工程(&R) - - - Save as New &Version - 保存爲新版本(&V) - - - E&xport Tracks... - 導出音軌(&X)... - - - Online Help - 在線幫助 - - - What's This? - 這是什麼? - - - Open Project - 打開工程 - - - Save Project - 保存工程 - - - Project recovery - 工程恢復 - - - There is a recovery file present. It looks like the last session did not end properly or another instance of LMMS is already running. Do you want to recover the project of this session? - 發現了一個恢復文件。看上去上個會話沒有正常結束或者其他的 LMMS 進程已經運行。你想要恢復這個項目嗎? - - - Recover - 恢復 - - - Recover the file. Please don't run multiple instances of LMMS when you do this. - 恢復文件。請不要在恢復文件時運行多個 LMMS 程序。 - - - Discard - 丟棄 - - - Launch a default session and delete the restored files. This is not reversible. - 運行一個新的默認會話並且刪除恢復文件。此操作無法撤銷。 - - - Preparing plugin browser - 正在準備插件瀏覽器 - - - Preparing file browsers - 正在準備文件瀏覽器 - - - Root directory - 根目錄 - - - Loading background artwork - 正在加載背景圖案 - - - New from template - 從模版新建工程 - - - Save as default template - 保存爲默認模板 - - - &View - 視圖 (&V) - - - Toggle metronome - 開啓/關閉節拍器 - - - Show/hide Song-Editor + + Song Editor 顯示/隱藏歌曲編輯器 - Show/hide Beat+Bassline Editor + + Beat+Bassline Editor 顯示/隱藏節拍+旋律編輯器 - Show/hide Piano-Roll + + Piano Roll 顯示/隱藏鋼琴窗 - Show/hide Automation Editor + + Automation Editor 顯示/隱藏自動控制編輯器 - Show/hide FX Mixer + + FX Mixer 顯示/隱藏混音器 - Show/hide project notes + + Project Notes 顯示/隱藏工程註釋 - Show/hide controller rack + + Controller Rack 顯示/隱藏控制器機架 - Recover session. Please save your work! - 恢復會話。請保存你的工作! - - - Recovered project not saved - 恢復的工程沒有保存 - - - This project was recovered from the previous session. It is currently unsaved and will be lost if you don't save it. Do you want to save it now? - 這個工程已從上一個會話中恢復。它現在沒有被保存, 並且如果你不保存, 它將會丟失。你現在想保存它嗎? - - - LMMS Project - LMMS 工程 - - - LMMS Project Template - LMMS 工程模板 - - - Overwrite default template? - 覆蓋默認的模板? - - - This will overwrite your current default template. - 這將會覆蓋你的當前默認模板。 - - - Smooth scroll - 平滑滾動 - - - Enable note labels in piano roll - 在鋼琴窗中顯示音號 - - - Save project template - - - + Volume as dBFS - Could not open file - 無法打開文件 + + Smooth scroll + 平滑滾動 - Could not open file %1 for writing. -Please make sure you have write permission to the file and the directory containing the file and try again! - - - - Export &MIDI... - 導出 MIDI (&M)... + + Enable note labels in piano roll + 在鋼琴窗中顯示音號 MeterDialog + + Meter Numerator + + Meter Denominator + TIME SIG 拍子記號 @@ -4145,10 +5159,12 @@ Please make sure you have write permission to the file and the directory contain MeterModel + Numerator + Denominator @@ -4156,10 +5172,12 @@ Please make sure you have write permission to the file and the directory contain MidiController + MIDI Controller MIDI控制器 + unnamed_midi_controller @@ -4167,18 +5185,23 @@ Please make sure you have write permission to the file and the directory contain MidiImport + + Setup incomplete 設置不完整 + You do not have set up a default soundfont in the settings dialog (Edit->Settings). Therefore no sound will be played back after importing this MIDI file. You should download a General MIDI soundfont, specify it in settings dialog and try again. 你還沒有在設置(在編輯->設置)中設置默認的 Soundfont。因此在導入此 MIDI 文件後將會沒有聲音。你需要下載一個通用 MIDI (GM) 的 Soundfont, 並且在設置對話框中選中後再試一次。 + You did not compile LMMS with support for SoundFont2 player, which is used to add default sound to imported MIDI files. Therefore no sound will be played back after importing this MIDI file. - 你在編譯 LMMS 時沒有加入 SoundFont2 播放器支持, 此播放器默認用於添加導入的 MIDI 文件。因此在 MIDI 文件導入後, 將沒有聲音。 + 您在編譯 LMMS 時未一併啟用 SoundFont2 播放器支援,此播放器用於為匯入的 MIDI 檔案加入預設聲音,因此在匯入此 MIDI 檔後不會有聲音。 + Track 軌道 @@ -4186,11 +5209,13 @@ Please make sure you have write permission to the file and the directory contain MidiJack + JACK server down When JACK(JACK Audio Connection Kit) disconnects, it will show the following message (title) JACK服務崩潰 + The JACK server seems to be shuted down. When JACK(JACK Audio Connection Kit) disconnects, it will show the following message (dialog message) @@ -4199,53 +5224,65 @@ Please make sure you have write permission to the file and the directory contain MidiPort + Input channel 輸入通道 + Output channel 輸出通道 + Input controller 輸入控制器 + Output controller 輸出控制器 + Fixed input velocity + Fixed output velocity - Output MIDI program - - - - Receive MIDI-events - 接受 MIDI 事件 - - - Send MIDI-events - 發送 MIDI 事件 - - + Fixed output note + + Output MIDI program + + + + Base velocity 基準力度 + + + Receive MIDI-events + 接受 MIDI 事件 + + + + Send MIDI-events + 發送 MIDI 事件 + MidiSetupWidget + DEVICE 設備 @@ -4253,474 +5290,595 @@ Please make sure you have write permission to the file and the directory contain MonstroInstrument + Osc 1 Volume + Osc 1 Panning + Osc 1 Coarse detune + Osc 1 Fine detune left + Osc 1 Fine detune right + Osc 1 Stereo phase offset + Osc 1 Pulse width + Osc 1 Sync send on rise + Osc 1 Sync send on fall + Osc 2 Volume + Osc 2 Panning + Osc 2 Coarse detune + Osc 2 Fine detune left + Osc 2 Fine detune right + Osc 2 Stereo phase offset + Osc 2 Waveform + Osc 2 Sync Hard + Osc 2 Sync Reverse + Osc 3 Volume + Osc 3 Panning + Osc 3 Coarse detune + Osc 3 Stereo phase offset + Osc 3 Sub-oscillator mix + Osc 3 Waveform 1 + Osc 3 Waveform 2 + Osc 3 Sync Hard + Osc 3 Sync Reverse + LFO 1 Waveform + LFO 1 Attack + LFO 1 Rate + LFO 1 Phase + LFO 2 Waveform + LFO 2 Attack + LFO 2 Rate + LFO 2 Phase + Env 1 Pre-delay + Env 1 Attack + Env 1 Hold + Env 1 Decay + Env 1 Sustain + Env 1 Release + Env 1 Slope + Env 2 Pre-delay + Env 2 Attack + Env 2 Hold + Env 2 Decay + Env 2 Sustain + Env 2 Release + Env 2 Slope + Osc2-3 modulation + Selected view + Vol1-Env1 + Vol1-Env2 + Vol1-LFO1 + Vol1-LFO2 + Vol2-Env1 + Vol2-Env2 + Vol2-LFO1 + Vol2-LFO2 + Vol3-Env1 + Vol3-Env2 + Vol3-LFO1 + Vol3-LFO2 + Phs1-Env1 + Phs1-Env2 + Phs1-LFO1 + Phs1-LFO2 + Phs2-Env1 + Phs2-Env2 + Phs2-LFO1 + Phs2-LFO2 + Phs3-Env1 + Phs3-Env2 + Phs3-LFO1 + Phs3-LFO2 + Pit1-Env1 + Pit1-Env2 + Pit1-LFO1 + Pit1-LFO2 + Pit2-Env1 + Pit2-Env2 + Pit2-LFO1 + Pit2-LFO2 + Pit3-Env1 + Pit3-Env2 + Pit3-LFO1 + Pit3-LFO2 + PW1-Env1 + PW1-Env2 + PW1-LFO1 + PW1-LFO2 + Sub3-Env1 + Sub3-Env2 + Sub3-LFO1 + Sub3-LFO2 + + Sine wave 正弦波 + Bandlimited Triangle wave + Bandlimited Saw wave + Bandlimited Ramp wave + Bandlimited Square wave + Bandlimited Moog saw wave + + Soft square wave + Absolute sine wave + + Exponential wave + White noise + Digital Triangle wave + Digital Saw wave + Digital Ramp wave + Digital Square wave + Digital Moog saw wave + Triangle wave 三角波 + Saw wave 鋸齒波 + Ramp wave + Square wave 方波 + Moog saw wave + Abs. sine wave + Random 隨機 + Random smooth @@ -4728,20 +5886,24 @@ Please make sure you have write permission to the file and the directory contain MonstroView + Operators view + The Operators view contains all the operators. These include both audible operators (oscillators) and inaudible operators, or modulators: Low-frequency oscillators and Envelopes. Knobs and other widgets in the Operators view have their own what's this -texts, so you can get more specific help for them that way. + Matrix view 矩陣視圖 + The Matrix view contains the modulation matrix. Here you can define the modulation relationships between the various operators: Each audible operator (oscillators 1-3) has 3-4 properties that can be modulated by any of the modulators. Using more modulations consumes more CPU power. The view is divided to modulation targets, grouped by the target oscillator. Available targets are volume, pitch, phase, pulse width and sub-osc ratio. Note: some targets are specific to one oscillator only. @@ -4750,256 +5912,407 @@ Each modulation target has 4 knobs, one for each modulator. By default the knobs + + + + Volume + 音量 + + + + + + Panning + 聲相 + + + + + + Coarse detune + + + + + + + semitones + 半音 + + + + + Finetune left + + + + + + + + cents + + + + + + Finetune right + + + + + + + Stereo phase offset + + + + + + + + + deg + + + + + Pulse width + + + + + Send sync on pulse rise + + + + + Send sync on pulse fall + + + + + Hard sync oscillator 2 + + + + + Reverse sync oscillator 2 + + + + + Sub-osc mix + + + + + Hard sync oscillator 3 + + + + + Reverse sync oscillator 3 + + + + + + + + Attack + 打進聲 + + + + + Rate + + + + + + Phase + + + + + + Pre-delay + + + + + + Hold + 保持 + + + + + Decay + 衰減 + + + + + Sustain + 持續 + + + + + Release + 釋放 + + + + + Slope + + + + Mix Osc2 with Osc3 + Modulate amplitude of Osc3 with Osc2 + Modulate frequency of Osc3 with Osc2 + Modulate phase of Osc3 with Osc2 + The CRS knob changes the tuning of oscillator 1 in semitone steps. + The CRS knob changes the tuning of oscillator 2 in semitone steps. + The CRS knob changes the tuning of oscillator 3 in semitone steps. + + + + FTL and FTR change the finetuning of the oscillator for left and right channels respectively. These can add stereo-detuning to the oscillator which widens the stereo image and causes an illusion of space. + + + The SPO knob modifies the difference in phase between left and right channels. Higher difference creates a wider stereo image. + The PW knob controls the pulse width, also known as duty cycle, of oscillator 1. Oscillator 1 is a digital pulse wave oscillator, it doesn't produce bandlimited output, which means that you can use it as an audible oscillator but it will cause aliasing. You can also use it as an inaudible source of a sync signal, which can be used to synchronize oscillators 2 and 3. + Send Sync on Rise: When enabled, the Sync signal is sent every time the state of oscillator 1 changes from low to high, ie. when the amplitude changes from -1 to 1. Oscillator 1's pitch, phase and pulse width may affect the timing of syncs, but its volume has no effect on them. Sync signals are sent independently for both left and right channels. + Send Sync on Fall: When enabled, the Sync signal is sent every time the state of oscillator 1 changes from high to low, ie. when the amplitude changes from 1 to -1. Oscillator 1's pitch, phase and pulse width may affect the timing of syncs, but its volume has no effect on them. Sync signals are sent independently for both left and right channels. + + Hard sync: Every time the oscillator receives a sync signal from oscillator 1, its phase is reset to 0 + whatever its phase offset is. + + Reverse sync: Every time the oscillator receives a sync signal from oscillator 1, the amplitude of the oscillator gets inverted. + Choose waveform for oscillator 2. + Choose waveform for oscillator 3's first sub-osc. Oscillator 3 can smoothly interpolate between two different waveforms. + Choose waveform for oscillator 3's second sub-osc. Oscillator 3 can smoothly interpolate between two different waveforms. + The SUB knob changes the mixing ratio of the two sub-oscs of oscillator 3. Each sub-osc can be set to produce a different waveform, and oscillator 3 can smoothly interpolate between them. All incoming modulations to oscillator 3 are applied to both sub-oscs/waveforms in the exact same way. + In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. Mix mode means no modulation: the outputs of the oscillators are simply mixed together. + In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. AM means amplitude modulation: Oscillator 3's amplitude (volume) is modulated by oscillator 2. + In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. FM means frequency modulation: Oscillator 3's frequency (pitch) is modulated by oscillator 2. The frequency modulation is implemented as phase modulation, which gives a more stable overall pitch than "pure" frequency modulation. + In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. PM means phase modulation: Oscillator 3's phase is modulated by oscillator 2. It differs from frequency modulation in that the phase changes are not cumulative. + Select the waveform for LFO 1. "Random" and "Random smooth" are special waveforms: they produce random output, where the rate of the LFO controls how often the state of the LFO changes. The smooth version interpolates between these states with cosine interpolation. These random modes can be used to give "life" to your presets - add some of that analog unpredictability... + Select the waveform for LFO 2. "Random" and "Random smooth" are special waveforms: they produce random output, where the rate of the LFO controls how often the state of the LFO changes. The smooth version interpolates between these states with cosine interpolation. These random modes can be used to give "life" to your presets - add some of that analog unpredictability... + + Attack causes the LFO to come on gradually from the start of the note. + + Rate sets the speed of the LFO, measured in milliseconds per cycle. Can be synced to tempo. + + PHS controls the phase offset of the LFO. + + PRE, or pre-delay, delays the start of the envelope from the start of the note. 0 means no delay. + + ATT, or attack, controls how fast the envelope ramps up at start, measured in milliseconds. A value of 0 means instant. + + HOLD controls how long the envelope stays at peak after the attack phase. + + DEC, or decay, controls how fast the envelope falls off from its peak, measured in milliseconds it would take to go from peak to zero. The actual decay may be shorter if sustain is used. + + SUS, or sustain, controls the sustain level of the envelope. The decay phase will not go below this level as long as the note is held. + + REL, or release, controls how long the release is for the note, measured in how long it would take to fall from peak to zero. Actual release may be shorter, depending on at what phase the note is released. + + The slope knob controls the curve or shape of the envelope. A value of 0 creates straight rises and falls. Negative values create curves that start slowly, peak quickly and fall of slowly again. Positive values create curves that start and end quickly, and stay longer near the peaks. - Volume - 音量 - - - Panning - 聲相 - - - Coarse detune - - - - semitones - 半音 - - - Finetune left - - - - cents - - - - Finetune right - - - - Stereo phase offset - - - - deg - - - - Pulse width - - - - Send sync on pulse rise - - - - Send sync on pulse fall - - - - Hard sync oscillator 2 - - - - Reverse sync oscillator 2 - - - - Sub-osc mix - - - - Hard sync oscillator 3 - - - - Reverse sync oscillator 3 - - - - Attack - 打進聲 - - - Rate - - - - Phase - - - - Pre-delay - - - - Hold - 保持 - - - Decay - 衰減 - - - Sustain - 持續 - - - Release - 釋放 - - - Slope - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Modulation amount 調製量 @@ -5007,34 +6320,42 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator MultitapEchoControlDialog + Length 長度 + Step length: 步進長度: + Dry 幹聲 + Dry Gain: 幹聲增益: + Stages + Lowpass stages: + Swap inputs + Swap left and right input channel for reflections @@ -5042,82 +6363,102 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator NesInstrument + Channel 1 Coarse detune + Channel 1 Volume + Channel 1 Envelope length + Channel 1 Duty cycle + Channel 1 Sweep amount + Channel 1 Sweep rate + Channel 2 Coarse detune + Channel 2 Volume + Channel 2 Envelope length + Channel 2 Duty cycle + Channel 2 Sweep amount + Channel 2 Sweep rate + Channel 3 Coarse detune + Channel 3 Volume + Channel 4 Volume + Channel 4 Envelope length + Channel 4 Noise frequency + Channel 4 Noise frequency sweep + Master volume 主音量 + Vibrato @@ -5125,114 +6466,155 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator NesInstrumentView + + + + Volume 音量 + + + Coarse detune + + + Envelope length + Enable channel 1 + Enable envelope 1 + Enable envelope 1 loop + Enable sweep 1 + + Sweep amount + + Sweep rate + + 12.5% Duty cycle + + 25% Duty cycle + + 50% Duty cycle + + 75% Duty cycle + Enable channel 2 + Enable envelope 2 + Enable envelope 2 loop + Enable sweep 2 + Enable channel 3 + Noise Frequency + Frequency sweep + Enable channel 4 + Enable envelope 4 + Enable envelope 4 loop + Quantize noise frequency when using note frequency + Use note frequency for noise + Noise mode + Master Volume 主音量 + Vibrato @@ -5240,81 +6622,103 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator OscillatorObject - Osc %1 volume - Osc %1 音量 - - - Osc %1 panning - Osc %1 聲像 - - - Osc %1 coarse detuning - - - - Osc %1 fine detuning left - - - - Osc %1 fine detuning right - - - - Osc %1 phase-offset - - - - Osc %1 stereo phase-detuning - - - - Osc %1 wave shape - - - - Modulation type %1 - - - + Osc %1 waveform Osc %1 波形 + Osc %1 harmonic + + + + Osc %1 volume + Osc %1 音量 + + + + + Osc %1 panning + Osc %1 聲像 + + + + + Osc %1 fine detuning left + + + + + Osc %1 coarse detuning + + + + + Osc %1 fine detuning right + + + + + Osc %1 phase-offset + + + + + Osc %1 stereo phase-detuning + + + + + Osc %1 wave shape + + + + + Modulation type %1 + + PatchesDialog + Qsynth: Channel Preset Qsynth: 通道預設 + Bank selector 音色選擇器 + Bank + Program selector + Patch 音色 + Name 名稱 + OK 確定 + Cancel 取消 @@ -5322,46 +6726,57 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator PatmanView + Open other patch 打開其他音色 + Click here to open another patch-file. Loop and Tune settings are not reset. 點擊這裏打開另一個音色文件。循環和調音設置不會被重設。 + Loop 循環 + Loop mode 循環模式 + Here you can toggle the Loop mode. If enabled, PatMan will use the loop information available in the file. 在這裏你可以開關循環模式。如果啓用,PatMan 會使用文件中的循環信息。 + Tune 調音 + Tune mode 調音模式 + Here you can toggle the Tune mode. If enabled, PatMan will tune the sample to match the note's frequency. 這裏可以開關調音模式。如果啓用,PatMan 會將採樣調成和音符一樣的頻率。 + No file selected - 未選擇文件 + 未選擇檔案 + Open patch file 打開音色文件 + Patch-Files (*.pat) 音色文件 (*.pat) @@ -5369,30 +6784,47 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator PatternView + + use mouse wheel to set velocity of a step + + + + + double-click to open in Piano Roll + + + + Open in piano-roll 在鋼琴窗中打開 + Clear all notes 清除所有音符 + Reset name 重置名稱 + Change name 修改名稱 + Add steps 添加音階 + Remove steps 移除音階 + Clone Steps @@ -5400,25 +6832,30 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator PeakController + Peak Controller 峯值控制器 + Peak Controller Bug 峯值控制器 Bug + Due to a bug in older version of LMMS, the peak controllers may not be connect properly. Please ensure that peak controllers are connected properly and re-save this file. Sorry for any inconvenience caused. - 在老版本的 LMMS 中, 峯值控制器因爲有 bug 而可能沒有正確連接。請確保峯值控制器正常連接後再次保存次文件。我們對給你造成的不便深表歉意。 + 由於在舊版 LMMS 中的錯誤,峰值控制器可能並未正確地連線。請確認峰值控制器正確地連線後再次儲存檔案。造成您的不便,深感抱歉。 PeakControllerDialog + PEAK + LFO Controller LFO 控制器 @@ -5426,306 +6863,382 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator PeakControllerEffectControlDialog + BASE 基準 + Base amount: 基礎值: - Modulation amount: - 調製量: - - - Attack: - 打擊聲: - - - Release: - 釋音: - - + AMNT + + Modulation amount: + 調製量: + + + MULT + Amount Multiplicator: + ATCK 打擊 + + Attack: + 打擊聲: + + + DCAY - Treshold: + + Release: + 釋音: + + + + TRSH - TRSH + + Treshold: PeakControllerEffectControls + Base value 基準值 + Modulation amount 調製量 - Mute output - 輸出靜音 - - + Attack 打進聲 + Release 釋放 + + Treshold + 閥值 + + + + Mute output + 輸出靜音 + + + Abs Value + Amount Multiplicator - - Treshold - 閥值 - PianoRoll - Please open a pattern by double-clicking on it! - 雙擊打開片段! - - - Last note - 上一個音符 - - - Note lock - 音符鎖定 - - + Note Velocity 音符音量 + Note Panning 音符聲相偏移 + Mark/unmark current semitone 標記/取消標記當前半音 - Mark current scale - - - - Mark current chord - - - - Unmark all - 取消標記所有 - - - No scale - - - - No chord - - - - Velocity: %1% - 音量:%1% - - - Panning: %1% left - 聲相:%1% 偏左 - - - Panning: %1% right - 聲相:%1% 偏右 - - - Panning: center - 聲相:居中 - - - Please enter a new value between %1 and %2: - 請輸入一個介於 %1 和 %2 的值: - - + Mark/unmark all corresponding octave semitones + + Mark current scale + + + + + Mark current chord + + + + + Unmark all + 取消標記所有 + + + Select all notes on this key 選中所有相同音調的音符 + + + Note lock + 音符鎖定 + + + + Last note + 上一個音符 + + + + No scale + + + + + No chord + + + + + Velocity: %1% + 音量:%1% + + + + Panning: %1% left + 聲相:%1% 偏左 + + + + Panning: %1% right + 聲相:%1% 偏右 + + + + Panning: center + 聲相:居中 + + + + Please open a pattern by double-clicking on it! + 雙擊打開片段! + + + + + Please enter a new value between %1 and %2: + 請輸入一個介於 %1 和 %2 的值: + PianoRollWindow + Play/pause current pattern (Space) 播放/暫停當前片段(空格) + Record notes from MIDI-device/channel-piano 從 MIDI 設備/通道鋼琴(channel-piano) 錄製音符 + Record notes from MIDI-device/channel-piano while playing song or BB track + Stop playing of current pattern (Space) 停止當前片段(空格) + Click here to play the current pattern. This is useful while editing it. The pattern is automatically looped when its end is reached. + Click here to record notes from a MIDI-device or the virtual test-piano of the according channel-window to the current pattern. When recording all notes you play will be written to this pattern and you can play and edit them afterwards. + Click here to record notes from a MIDI-device or the virtual test-piano of the according channel-window to the current pattern. When recording all notes you play will be written to this pattern and you will hear the song or BB track in the background. + Click here to stop playback of current pattern. - Draw mode (Shift+D) - 繪製模式 (Shift+D) - - - Erase mode (Shift+E) - 擦除模式 (Shift+E) - - - Select mode (Shift+S) - 選擇模式 (Shift+S) - - - Detune mode (Shift+T) - - - - Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold %1 to temporarily go into select mode. - - - - Click here and erase mode will be activated. In this mode you can erase notes. You can also press 'Shift+E' on your keyboard to activate this mode. - 點擊啓用擦除模式。此模式下你可以擦除音符。你可以按鍵盤上的 'Shift+E' 啓用此模式。 - - - Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold %1 in draw mode to temporarily use select mode. - - - - Click here and detune mode will be activated. In this mode you can click a note to open its automation detuning. You can utilize this to slide notes from one to another. You can also press 'Shift+T' on your keyboard to activate this mode. - - - - Cut selected notes (%1+X) - 剪切選定音符 (%1+X) - - - Copy selected notes (%1+C) - 複製選定音符 (%1+C) - - - Paste notes from clipboard (%1+V) - 從剪貼板粘貼音符 (%1+V) - - - Click here and the selected notes will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. - - - - Click here and the selected notes will be copied into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. - - - - Click here and the notes from the clipboard will be pasted at the first visible measure. - - - - This controls the magnification of an axis. It can be helpful to choose magnification for a specific task. For ordinary editing, the magnification should be fitted to your smallest notes. - - - - The 'Q' stands for quantization, and controls the grid size notes and control points snap to. With smaller quantization values, you can draw shorter notes in Piano Roll, and more exact control points in the Automation Editor. - - - - This lets you select the length of new notes. 'Last Note' means that LMMS will use the note length of the note you last edited - - - - The feature is directly connected to the context-menu on the virtual keyboard, to the left in Piano Roll. After you have chosen the scale you want in this drop-down menu, you can right click on a desired key in the virtual keyboard, and then choose 'Mark current Scale'. LMMS will highlight all notes that belongs to the chosen scale, and in the key you have selected! - - - - Let you select a chord which LMMS then can draw or highlight.You can find the most common chords in this drop-down menu. After you have selected a chord, click anywhere to place the chord, and right click on the virtual keyboard to open context menu and highlight the chord. To return to single note placement, you need to choose 'No chord' in this drop-down menu. - - - + Edit actions 編輯功能 + + Draw mode (Shift+D) + 繪製模式 (Shift+D) + + + + Erase mode (Shift+E) + 擦除模式 (Shift+E) + + + + Select mode (Shift+S) + 選擇模式 (Shift+S) + + + + Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold %1 to temporarily go into select mode. + + + + + Click here and erase mode will be activated. In this mode you can erase notes. You can also press 'Shift+E' on your keyboard to activate this mode. + 點擊啓用擦除模式。此模式下你可以擦除音符。你可以按鍵盤上的 'Shift+E' 啓用此模式。 + + + + Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold %1 in draw mode to temporarily use select mode. + + + + + Pitch Bend mode (Shift+T) + + + + + Click here and Pitch Bend mode will be activated. In this mode you can click a note to open its automation detuning. You can utilize this to slide notes from one to another. You can also press 'Shift+T' on your keyboard to activate this mode. + + + + + Quantize + + + + Copy paste controls + + Cut selected notes (%1+X) + 剪切選定音符 (%1+X) + + + + Copy selected notes (%1+C) + 複製選定音符 (%1+C) + + + + Paste notes from clipboard (%1+V) + 從剪貼板粘貼音符 (%1+V) + + + + Click here and the selected notes will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. + + + + + Click here and the selected notes will be copied into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. + + + + + Click here and the notes from the clipboard will be pasted at the first visible measure. + + + + Timeline controls 時間線控制 + Zoom and note controls + + This controls the magnification of an axis. It can be helpful to choose magnification for a specific task. For ordinary editing, the magnification should be fitted to your smallest notes. + + + + + The 'Q' stands for quantization, and controls the grid size notes and control points snap to. With smaller quantization values, you can draw shorter notes in Piano Roll, and more exact control points in the Automation Editor. + + + + + This lets you select the length of new notes. 'Last Note' means that LMMS will use the note length of the note you last edited + + + + + The feature is directly connected to the context-menu on the virtual keyboard, to the left in Piano Roll. After you have chosen the scale you want in this drop-down menu, you can right click on a desired key in the virtual keyboard, and then choose 'Mark current Scale'. LMMS will highlight all notes that belongs to the chosen scale, and in the key you have selected! + + + + + Let you select a chord which LMMS then can draw or highlight.You can find the most common chords in this drop-down menu. After you have selected a chord, click anywhere to place the chord, and right click on the virtual keyboard to open context menu and highlight the chord. To return to single note placement, you need to choose 'No chord' in this drop-down menu. + + + + + Piano-Roll - %1 鋼琴窗 - %1 + + Piano-Roll - no pattern 鋼琴窗 - 沒有片段 - - Quantize - - PianoView + Base note 基本音 @@ -5733,20 +7246,24 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator Plugin + Plugin not found 未找到插件 + The plugin "%1" wasn't found or could not be loaded! Reason: "%2" 插件“%1”無法找到或無法載入! 原因:%2 + Error while loading plugin 載入插件時發生錯誤 + Failed to load plugin "%1"! 載入插件“%1”失敗! @@ -5754,25 +7271,30 @@ Reason: "%2" PluginBrowser + + Instrument Plugins + + + + Instrument browser 樂器瀏覽器 + Drag an instrument into either the Song-Editor, the Beat+Bassline Editor or into an existing instrument track. 將樂器插件拖入歌曲編輯器, 節拍低音線編輯器, 或者現有的樂器軌道。 - - Instrument Plugins - - PluginFactory + Plugin not found. 未找到插件。 + LMMS plugin %1 does not have a plugin descriptor named %2! @@ -5780,129 +7302,160 @@ Reason: "%2" ProjectNotes - Edit Actions - 編輯功能 - - - &Undo - 撤銷(&U) - - - %1+Z - %1+Z - - - &Redo - 重做(&R) - - - %1+Y - %1+Y - - - &Copy - 複製(&C) - - - %1+C - %1+C - - - Cu&t - 剪切(&T) - - - %1+X - %1+X - - - &Paste - 粘貼(&P) - - - %1+V - %1+V - - - Format Actions - 格式功能 - - - &Bold - 加粗(&B) - - - %1+B - %1+B - - - &Italic - 斜體(&I) - - - %1+I - %1+I - - - &Underline - 下劃線(&U) - - - %1+U - %1+U - - - &Left - 左對齊(&L) - - - %1+L - %1+L - - - C&enter - 居中(&E) - - - %1+E - %1+E - - - &Right - 右對齊(&R) - - - %1+R - %1+R - - - &Justify - 勻齊(&J) - - - %1+J - %1+J - - - &Color... - 顏色(&C)... - - + Project Notes 顯示/隱藏工程註釋 + Enter project notes here + + + Edit Actions + 編輯功能 + + + + &Undo + 撤銷(&U) + + + + %1+Z + %1+Z + + + + &Redo + 重做(&R) + + + + %1+Y + %1+Y + + + + &Copy + 複製(&C) + + + + %1+C + %1+C + + + + Cu&t + 剪切(&T) + + + + %1+X + %1+X + + + + &Paste + 粘貼(&P) + + + + %1+V + %1+V + + + + Format Actions + 格式功能 + + + + &Bold + 加粗(&B) + + + + %1+B + %1+B + + + + &Italic + 斜體(&I) + + + + %1+I + %1+I + + + + &Underline + 下劃線(&U) + + + + %1+U + %1+U + + + + &Left + 左對齊(&L) + + + + %1+L + %1+L + + + + C&enter + 居中(&E) + + + + %1+E + %1+E + + + + &Right + 右對齊(&R) + + + + %1+R + %1+R + + + + &Justify + 勻齊(&J) + + + + %1+J + %1+J + + + + &Color... + 顏色(&C)... + ProjectRenderer + WAV-File (*.wav) WAV-文件 (*.wav) + Compressed OGG-File (*.ogg) 壓縮的 OGG 文件(*.ogg) @@ -5911,6 +7464,7 @@ Reason: "%2" + Compressed MP3-File (*.mp3) @@ -5918,57 +7472,89 @@ Reason: "%2" QWidget + + + Name: 名稱: + + Maker: 製作者: + + Copyright: 版權: + + Requires Real Time: 要求實時: + + + + + + Yes + + + + + + No + + Real Time Capable: 是否支持實時: + + In Place Broken: + + Channels In: 輸入通道: + + Channels Out: 輸出通道: - File: - 文件: + + File: %1 + 檔案:%1 - File: %1 - 文件:%1 + + File: + 檔案: RenameDialog + Rename... 重命名... @@ -5976,34 +7562,42 @@ Reason: "%2" ReverbSCControlDialog + Input 輸入 + Input Gain: 輸入增益: + Size + Size: + Color + Color: + Output 輸出 + Output Gain: 輸出增益: @@ -6011,18 +7605,22 @@ Reason: "%2" ReverbSCControls + Input Gain + Size + Color + Output Gain @@ -6030,81 +7628,100 @@ Reason: "%2" SampleBuffer - Open audio file - 打開音頻文件 - - - Wave-Files (*.wav) - Wave波形文件 (*.wav) - - - OGG-Files (*.ogg) - OGG-文件 (*.ogg) - - - DrumSynth-Files (*.ds) - DrumSynth-文件 (*.ds) - - - FLAC-Files (*.flac) - FLAC-文件 (*.flac) - - - SPEEX-Files (*.spx) - SPEEX-文件 (*.spx) - - - VOC-Files (*.voc) - VOC-文件 (*.voc) - - - AIFF-Files (*.aif *.aiff) - AIFF-文件 (*.aif *.aiff) - - - AU-Files (*.au) - AU-文件 (*.au) - - - RAW-Files (*.raw) - RAW-文件 (*.raw) - - - All Audio-Files (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw) - 所有音頻文件 (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw) - - + Fail to open file - + 無法開啟檔案 + Audio files are limited to %1 MB in size and %2 minutes of playing time - + 音訊檔案的檔案大小已限制為 %1 MB,播放時間已限制為 %2 分鐘。 + + + + Open audio file + 開啟音訊檔案 + + + + All Audio-Files (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw) + 所有音訊檔案 (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw) + + + + Wave-Files (*.wav) + Wave 波形檔案 (*.wav) + + + + OGG-Files (*.ogg) + OGG 檔案 (*.ogg) + + + + DrumSynth-Files (*.ds) + DrumSynth 檔案 (*.ds) + + + + FLAC-Files (*.flac) + FLAC 檔案 (*.flac) + + + + SPEEX-Files (*.spx) + SPEEX 檔案 (*.spx) + + + + VOC-Files (*.voc) + VOC 檔案 (*.voc) + + + + AIFF-Files (*.aif *.aiff) + AIFF 檔案 (*.aif *.aiff) + + + + AU-Files (*.au) + AU 檔案 (*.au) + + + + RAW-Files (*.raw) + RAW 檔案 (*.raw) SampleTCOView + double-click to select sample 雙擊選擇採樣 + Delete (middle mousebutton) 刪除 (鼠標中鍵) + Cut 剪切 + Copy 複製 + Paste 粘貼 + Mute/unmute (<%1> + middle click) 靜音/取消靜音 (<%1> + 鼠標中鍵) @@ -6112,41 +7729,51 @@ Reason: "%2" SampleTrack - Sample track - 採樣軌道 - - + Volume 音量 + Panning 聲相 + + + + Sample track + 採樣軌道 + SampleTrackView + Track volume 軌道音量 + Channel volume: 通道音量: + VOL VOL + Panning 聲相 + Panning: 聲相: + PAN PAN @@ -6154,496 +7781,658 @@ Reason: "%2" SetupDialog + Setup LMMS 設置LMMS + + General settings 常規設置 + BUFFER SIZE 緩衝區大小 + + Reset to default-value 重置爲默認值 + MISC 雜項 + Enable tooltips 啓用工具提示 + Show restart warning after changing settings 在改變設置後顯示重啓警告 - Compress project files per default - 默認壓縮項目文件 + + Display volume as dBFS + + + Compress project files per default + 預設壓縮專案檔 + + + One instrument track window mode 單樂器軌道窗口模式 + HQ-mode for output audio-device 對輸出設備使用高質量輸出 + Compact track buttons 緊湊化軌道圖標 + Sync VST plugins to host playback 同步 VST 插件和主機回放 + Enable note labels in piano roll 在鋼琴窗中顯示音號 + Enable waveform display by default 默認啓用波形圖 + Keep effects running even without input 在沒有輸入時也運行音頻效果 + Create backup file when saving a project - 保存工程時建立備份 + 儲存專案時建立備份檔 + + Reopen last project on start + 啓動時打開最近的項目 + + + + Use built-in NaN handler + + + + + PLUGIN EMBEDDING + + + + + No embedding + + + + + Embed using Qt API + + + + + Embed using native Win32 API + + + + + Embed using XEmbed protocol + + + + LANGUAGE 語言 + + Paths 路徑 + + Directories + 目錄 + + + LMMS working directory LMMS工作目錄 - VST-plugin directory - VST插件目錄 + + Themes directory + 主題文件目錄 + Background artwork 背景圖片 + + VST-plugin directory + VST插件目錄 + + + + GIG directory + GIG 目錄 + + + + SF2 directory + SF2 目錄 + + + + LADSPA plugin directories + LADSPA 插件目錄 + + + STK rawwave directory STK rawwave 目錄 + Default Soundfont File - 默認 SoundFont 文件 + 預設 SoundFont 檔案 + + Performance settings 性能設置 + + Auto save + 自動保存 + + + + Enable auto-save + + + + + Allow auto-save while playing + + + + UI effects vs. performance 界面特效 vs 性能 + Smooth scroll in Song Editor 歌曲編輯器中啓用平滑滾動 + Show playback cursor in AudioFileProcessor - 在 AudioFileProcessor 中顯示回放光標 + 在 AudioFileProcessor 中顯示播放指標 + + Audio settings 音頻設置 + AUDIO INTERFACE 音頻接口 + + MIDI settings MIDI設置 + MIDI INTERFACE MIDI接口 + OK 確定 + Cancel 取消 + Restart LMMS 重啓LMMS + Please note that most changes won't take effect until you restart LMMS! 請注意很多設置需要重啓LMMS纔可生效! + Frames: %1 Latency: %2 ms 幀數: %1 延遲: %2 毫秒 + Here you can setup the internal buffer-size used by LMMS. Smaller values result in a lower latency but also may cause unusable sound or bad performance, especially on older computers or systems with a non-realtime kernel. 在這裏,你可以設置 LMMS 所用緩衝區的大小。緩衝區越小,延遲越小,但聲音質量和性能可能會受影響。 + Choose LMMS working directory 選擇 LMMS 工作目錄 - Choose your VST-plugin directory - 選擇 VST 插件目錄 - - - Choose artwork-theme directory - 選擇插圖目錄 - - - Choose LADSPA plugin directory - 選擇 LADSPA 插件目錄 - - - Choose STK rawwave directory - 選擇 STK rawwave 目錄 - - - Choose default SoundFont - 選擇默認的 SoundFont - - - Choose background artwork - 選擇背景圖片 - - - Here you can select your preferred audio-interface. Depending on the configuration of your system during compilation time you can choose between ALSA, JACK, OSS and more. Below you see a box which offers controls to setup the selected audio-interface. - 在這裏你可以選擇你想要的音頻接口。取決於你的系統和編譯時的設置, 你可以選擇 ALSA, JACK, OSS 等選項。在下面的方框中你可以設置音頻接口的控制項目。 - - - Here you can select your preferred MIDI-interface. Depending on the configuration of your system during compilation time you can choose between ALSA, OSS and more. Below you see a box which offers controls to setup the selected MIDI-interface. - 在這裏你可以選擇你想要的 MIDI 接口。取決於你的系統和編譯時的設置, 你可以選擇 ALSA, OSS 等選項。在下面的方框中你可以設置 MIDI 接口的控制項目。 - - - Reopen last project on start - 啓動時打開最近的項目 - - - Directories - 目錄 - - - Themes directory - 主題文件目錄 - - - GIG directory - GIG 目錄 - - - SF2 directory - SF2 目錄 - - - LADSPA plugin directories - LADSPA 插件目錄 - - - Auto save - 自動保存 - - + Choose your GIG directory 選擇 GIG 目錄 + Choose your SF2 directory 選擇 SF2 目錄 + + Choose your VST-plugin directory + 選擇 VST 插件目錄 + + + + Choose artwork-theme directory + 選擇插圖目錄 + + + + Choose LADSPA plugin directory + 選擇 LADSPA 插件目錄 + + + + Choose STK rawwave directory + 選擇 STK rawwave 目錄 + + + + Choose default SoundFont + 選擇默認的 SoundFont + + + + Choose background artwork + 選擇背景圖片 + + + minutes 分鐘 + minute 分鐘 - Display volume as dBFS - - - - Enable auto-save - - - - Allow auto-save while playing - - - + Disabled + Auto-save interval: %1 + Set the time between automatic backup to %1. Remember to also save your project manually. You can choose to disable saving while playing, something some older systems find difficult. + + + Here you can select your preferred audio-interface. Depending on the configuration of your system during compilation time you can choose between ALSA, JACK, OSS and more. Below you see a box which offers controls to setup the selected audio-interface. + 在這裏你可以選擇你想要的音頻接口。取決於你的系統和編譯時的設置, 你可以選擇 ALSA, JACK, OSS 等選項。在下面的方框中你可以設置音頻接口的控制項目。 + + + + Here you can select your preferred MIDI-interface. Depending on the configuration of your system during compilation time you can choose between ALSA, OSS and more. Below you see a box which offers controls to setup the selected MIDI-interface. + 在這裏你可以選擇你想要的 MIDI 接口。取決於你的系統和編譯時的設置, 你可以選擇 ALSA, OSS 等選項。在下面的方框中你可以設置 MIDI 接口的控制項目。 + Song + Tempo 節奏 + Master volume 主音量 + Master pitch 主音高 - Project saved - 工程已保存 - - - The project %1 is now saved. - 工程 %1 已保存。 - - - Project NOT saved. - 工程 **沒有** 保存。 - - - The project %1 was not saved! - 工程%1沒有保存! - - - Import file - 導入文件 - - - MIDI sequences - MIDI 音序器 - - - Hydrogen projects - Hydrogen工程 - - - All file types - 所有類型 - - - Empty project - 空工程 - - - This project is empty so exporting makes no sense. Please put some items into Song Editor first! - 這個工程是空的所以就算導出也沒有意義,請在歌曲編輯器中加入一點聲音吧! - - - Select directory for writing exported tracks... - 選擇寫入導出音軌的目錄... - - - untitled - 未標題 - - - Select file for project-export... - 爲工程導出選擇文件... - - - The following errors occured while loading: - 載入時發生以下錯誤: - - - MIDI File (*.mid) - MIDI 文件 (*.mid) - - + LMMS Error report LMMS錯誤報告 + + Project saved + 工程已保存 + + + + The project %1 is now saved. + 工程 %1 已保存。 + + + + Project NOT saved. + 工程 **沒有** 保存。 + + + + The project %1 was not saved! + 工程%1沒有保存! + + + + Import file + 匯入檔案 + + + + MIDI sequences + MIDI 音序器 + + + + Hydrogen projects + Hydrogen工程 + + + + All file types + 所有檔案類型 + + + + + Empty project + 空工程 + + + + + This project is empty so exporting makes no sense. Please put some items into Song Editor first! + 這個工程是空的所以就算導出也沒有意義,請在歌曲編輯器中加入一點聲音吧! + + + + Select directory for writing exported tracks... + 選擇寫入導出音軌的目錄... + + + + + untitled + 未命名 + + + + + Select file for project-export... + 匯出專案至… + + + Save project + + + MIDI File (*.mid) + MIDI 檔案 (*.mid) + + + + The following errors occured while loading: + 載入時發生以下錯誤: + SongEditor + Could not open file - 無法打開文件 - - - Could not write file - 無法寫入文件 + 無法開啟檔案 + Could not open file %1. You probably have no permissions to read this file. Please make sure to have at least read permissions to the file and try again. - 無法打開 %1 。或許沒有權限讀此文件。 -請確保您擁有對此文件的讀權限,然後重試。 + 無法開啟 %1。 +請確認您至少有權限讀取此檔案後再試一次。 - Error in file - 文件錯誤 - - - The file %1 seems to contain errors and therefore can't be loaded. - 文件 %1 似乎包含錯誤,無法被加載。 - - - Tempo - 節奏 - - - TEMPO/BPM - 節奏/BPM - - - tempo of song - 歌曲的節奏 - - - The tempo of a song is specified in beats per minute (BPM). If you want to change the tempo of your song, change this value. Every measure has four beats, so the tempo in BPM specifies, how many measures / 4 should be played within a minute (or how many measures should be played within four minutes). - - - - High quality mode - 高質量模式 - - - Master volume - 主音量 - - - master volume - 主音量 - - - Master pitch - 主音高 - - - master pitch - 主音高 - - - Value: %1% - 值: %1% - - - Value: %1 semitones - 值: %1 半音程 + + Could not write file + 無法寫入檔案 + Could not open %1 for writing. You probably are not permitted to write to this file. Please make sure you have write-access to the file and try again. - 無法打開 %1 寫入數據。或許沒有權限修改此文件。請確保您擁有對此文件的寫權限,然後重試。 + 無法開啟 %1 以進行寫入。請確認您有權限寫入此檔案後再試一次。 - template - + + Error in file + 於檔案中發現錯誤 - project - + + The file %1 seems to contain errors and therefore can't be loaded. + 檔案 %1 似乎包含錯誤,無法進行載入。 + Version difference + This %1 was created with LMMS %2. + + + template + + + + + project + + + + + Tempo + 節奏 + + + + TEMPO/BPM + 節奏/BPM + + + + tempo of song + 歌曲的節奏 + + + + The tempo of a song is specified in beats per minute (BPM). If you want to change the tempo of your song, change this value. Every measure has four beats, so the tempo in BPM specifies, how many measures / 4 should be played within a minute (or how many measures should be played within four minutes). + + + + + High quality mode + 高質量模式 + + + + + Master volume + 主音量 + + + + master volume + 主音量 + + + + + Master pitch + 主音高 + + + + master pitch + 主音高 + + + + Value: %1% + 值: %1% + + + + Value: %1 semitones + 值: %1 半音程 + SongEditorWindow + Song-Editor 歌曲編輯器 + Play song (Space) 播放歌曲(空格) + Record samples from Audio-device 從音頻設備錄製樣本 + Record samples from Audio-device while playing song or BB track 在播放歌曲或BB軌道時從音頻設備錄入樣本 + Stop song (Space) 停止歌曲(空格) - Add beat/bassline - 添加節拍/Bassline - - - Add sample-track - 添加採樣軌道 - - - Add automation-track - 添加自動控制軌道 - - - Draw mode - 繪製模式 - - - Edit mode (select and move) - 編輯模式(選定和移動) - - + Click here, if you want to play your whole song. Playing will be started at the song-position-marker (green). You can also move it while playing. 點擊這裏完整播放歌曲。將從綠色歌曲標記開始播放。在播放的同時可以對它進行移動。 + Click here, if you want to stop playing of your song. The song-position-marker will be set to the start of your song. 點擊這裏停止播放,歌曲位置標記會跳到歌曲的開頭。 + Track actions 軌道動作 + + Add beat/bassline + 添加節拍/Bassline + + + + Add sample-track + 添加採樣軌道 + + + + Add automation-track + 添加自動控制軌道 + + + Edit actions 編輯動作 + + Draw mode + 繪製模式 + + + + Edit mode (select and move) + 編輯模式(選定和移動) + + + Timeline controls 時間線控制 + Zoom controls 縮放控制 @@ -6651,10 +8440,12 @@ Remember to also save your project manually. You can choose to disable saving wh SpectrumAnalyzerControlDialog + Linear spectrum 線性頻譜圖 + Linear Y axis 線性 Y 軸 @@ -6662,14 +8453,17 @@ Remember to also save your project manually. You can choose to disable saving wh SpectrumAnalyzerControls + Linear spectrum 線性頻譜圖 + Linear Y axis 線性 Y 軸 + Channel mode 通道模式 @@ -6677,14 +8471,17 @@ Remember to also save your project manually. You can choose to disable saving wh SubWindow + Close + Maximize + Restore @@ -6692,6 +8489,8 @@ Remember to also save your project manually. You can choose to disable saving wh TabWidget + + Settings for %1 %1 的設定 @@ -6699,74 +8498,93 @@ Remember to also save your project manually. You can choose to disable saving wh TempoSyncKnob + + Tempo Sync + No Sync 無同步 + Eight beats + Whole note + Half note + Quarter note + 8th note + 16th note + 32nd note + Custom... + Custom + Synced to Eight Beats + Synced to Whole Note + Synced to Half Note + Synced to Quarter Note + Synced to 8th Note + Synced to 16th Note + Synced to 32nd Note @@ -6774,30 +8592,37 @@ Remember to also save your project manually. You can choose to disable saving wh TimeDisplayWidget + click to change time units 點擊改變時間單位 + MIN + SEC + MSEC + BAR + BEAT + TICK @@ -6805,34 +8630,43 @@ Remember to also save your project manually. You can choose to disable saving wh TimeLineWidget + Enable/disable auto-scrolling 啓用/禁用自動滾動 + Enable/disable loop-points 啓用/禁用循環點 + After stopping go back to begin 停止後前往開頭 + After stopping go back to position at which playing was started 停止後前往播放開始的地方 + After stopping keep position 停止後保持位置不變 + + Hint 提示 + Press <%1> to disable magnetic loop points. 按住 <%1> 禁用磁性吸附。 + Hold <Shift> to move the begin loop point; Press <%1> to disable magnetic loop points. 按住 <Shift> 移動起始循環點;按住 <%1> 禁用磁性吸附。 @@ -6840,10 +8674,12 @@ Remember to also save your project manually. You can choose to disable saving wh Track + Mute 靜音 + Solo 獨奏 @@ -6851,49 +8687,71 @@ Remember to also save your project manually. You can choose to disable saving wh TrackContainer + Couldn't import file - 無法導入文件 + 無法匯入檔案 + Couldn't find a filter for importing file %1. You should convert this file into a format supported by LMMS using another software. - 無法找到導入文件 %1 的導入器 -你需要使用其他軟件將此文件轉換成 LMMS 支持的格式。 + 不支援 %1 的檔案類型。 +請使用其他軟體將此檔案轉換成 LMMS 支援的格式。 + Couldn't open file - 無法打開文件 + 無法開啟檔案 + Couldn't open file %1 for reading. Please make sure you have read-permission to the file and the directory containing the file and try again! - 無法讀取文件 %1 -請確認你有對該文件及其目錄的讀取權限後再試! + 無法開啟 %1。 +請確認您有權限讀取此檔案,以及包含此檔案的目錄後再試一次。 + Loading project... 正在加載工程... + + Cancel 取消 + + Please wait... 請稍等... - Importing MIDI-file... - 正在導入 MIDI-文件... + + Loading cancelled + + + Project loading was cancelled. + + + + Loading Track %1 (%2/Total %3) + + + Importing MIDI-file... + 正在匯入 MIDI 檔案… + TrackContentObject + Mute 靜音 @@ -6901,46 +8759,59 @@ Please make sure you have read-permission to the file and the directory containi TrackContentObjectView + Current position 當前位置 + + Hint 提示 + Press <%1> and drag to make a copy. 按住 <%1> 並拖動以創建副本。 + Current length 當前長度 + Press <%1> for free resizing. 按住 <%1> 自由調整大小。 + + %1:%2 (%3:%4 to %5:%6) %1:%2 (%3:%4 到 %5:%6) + Delete (middle mousebutton) 刪除 (鼠標中鍵) + Cut 剪切 + Copy 複製 + Paste 粘貼 + Mute/unmute (<%1> + middle click) 靜音/取消靜音 (<%1> + 鼠標中鍵) @@ -6948,193 +8819,243 @@ Please make sure you have read-permission to the file and the directory containi TrackOperationsWidget + Press <%1> while clicking on move-grip to begin a new drag'n'drop-action. + Actions for this track + Mute 靜音 + + Solo 獨奏 + Mute this track + Clone this track + Remove this track + Clear this track + FX %1: %2 效果 %1: %2 + + Assign to new FX Channel + + + + Turn all recording on + Turn all recording off - - Assign to new FX Channel - - TripleOscillatorView + Use phase modulation for modulating oscillator 1 with oscillator 2 + Use amplitude modulation for modulating oscillator 1 with oscillator 2 + Mix output of oscillator 1 & 2 + Synchronize oscillator 1 with oscillator 2 + Use frequency modulation for modulating oscillator 1 with oscillator 2 + Use phase modulation for modulating oscillator 2 with oscillator 3 + Use amplitude modulation for modulating oscillator 2 with oscillator 3 + Mix output of oscillator 2 & 3 + Synchronize oscillator 2 with oscillator 3 + Use frequency modulation for modulating oscillator 2 with oscillator 3 + Osc %1 volume: + With this knob you can set the volume of oscillator %1. When setting a value of 0 the oscillator is turned off. Otherwise you can hear the oscillator as loud as you set it here. + Osc %1 panning: + With this knob you can set the panning of the oscillator %1. A value of -100 means 100% left and a value of 100 moves oscillator-output right. + Osc %1 coarse detuning: + semitones + With this knob you can set the coarse detuning of oscillator %1. You can detune the oscillator 24 semitones (2 octaves) up and down. This is useful for creating sounds with a chord. + Osc %1 fine detuning left: + + cents 音分 cents + With this knob you can set the fine detuning of oscillator %1 for the left channel. The fine-detuning is ranged between -100 cents and +100 cents. This is useful for creating "fat" sounds. + Osc %1 fine detuning right: + With this knob you can set the fine detuning of oscillator %1 for the right channel. The fine-detuning is ranged between -100 cents and +100 cents. This is useful for creating "fat" sounds. + Osc %1 phase-offset: + + degrees + With this knob you can set the phase-offset of oscillator %1. That means you can move the point within an oscillation where the oscillator begins to oscillate. For example if you have a sine-wave and have a phase-offset of 180 degrees the wave will first go down. It's the same with a square-wave. + Osc %1 stereo phase-detuning: + With this knob you can set the stereo phase-detuning of oscillator %1. The stereo phase-detuning specifies the size of the difference between the phase-offset of left and right channel. This is very good for creating wide stereo sounds. + Use a sine-wave for current oscillator. 爲當前振盪器使用正弦波。 + Use a triangle-wave for current oscillator. 爲當前振盪器使用三角波。 + Use a saw-wave for current oscillator. 爲當前振盪器使用鋸齒波。 + Use a square-wave for current oscillator. 爲當前振盪器使用方波。 + Use a moog-like saw-wave for current oscillator. + Use an exponential wave for current oscillator. + Use white-noise for current oscillator. 爲當前振盪器使用白噪音。 + Use a user-defined waveform for current oscillator. 爲當前振盪器使用用戶自定波形。 @@ -7142,14 +9063,17 @@ Please make sure you have read-permission to the file and the directory containi VersionedSaveDialog + Increment version number 遞增版本號 + Decrement version number 遞減版本號 + already exists. Do you want to replace it? @@ -7157,90 +9081,113 @@ Please make sure you have read-permission to the file and the directory containi VestigeInstrumentView + Open other VST-plugin 打開其他的VST插件 + Click here, if you want to open another VST-plugin. After clicking on this button, a file-open-dialog appears and you can select your file. - Show/hide GUI - 顯示/隱藏界面 - - - Click here to show or hide the graphical user interface (GUI) of your VST-plugin. - 點此顯示/隱藏VST插件的界面。 - - - Turn off all notes - 全部靜音 - - - Open VST-plugin - 打開VST插件 - - - DLL-files (*.dll) - DLL-文件 (*.dll) - - - EXE-files (*.exe) - EXE-文件 (*.exe) - - - No VST-plugin loaded - 未載入VST插件 - - + Control VST-plugin from LMMS host 從 LMMS 宿主控制 VST-插件 + Click here, if you want to control VST-plugin from host. + Open VST-plugin preset 打開 VST-插件預設 + Click here, if you want to open another *.fxp, *.fxb VST-plugin preset. + Previous (-) 上一個 (-) + + Click here, if you want to switch to another VST-plugin preset program. + Save preset 保存預置 + Click here, if you want to save current VST-plugin preset program. 點擊這裏, 如果你想保存當前 VST-插件預設。 + Next (+) 下一個 (+) + Click here to select presets that are currently loaded in VST. + + Show/hide GUI + 顯示/隱藏界面 + + + + Click here to show or hide the graphical user interface (GUI) of your VST-plugin. + 點此顯示/隱藏VST插件的界面。 + + + + Turn off all notes + 全部靜音 + + + + Open VST-plugin + 打開VST插件 + + + + DLL-files (*.dll) + DLL 檔案 (*.dll) + + + + EXE-files (*.exe) + EXE 檔案 (*.exe) + + + + No VST-plugin loaded + 未載入VST插件 + + + Preset 預置 + by + - VST plugin control - VST插件控制 @@ -7248,10 +9195,12 @@ Please make sure you have read-permission to the file and the directory containi VisualizationWidget + click to enable/disable visualization of master-output 點擊啓用/禁用視覺化主輸出 + Click to enable 點擊啓用 @@ -7259,54 +9208,69 @@ Please make sure you have read-permission to the file and the directory containi VstEffectControlDialog + Show/hide 顯示/隱藏 + Control VST-plugin from LMMS host 從 LMMS 宿主控制 VST-插件 + Click here, if you want to control VST-plugin from host. + Open VST-plugin preset 打開 VST-插件預設 + Click here, if you want to open another *.fxp, *.fxb VST-plugin preset. + Previous (-) 上一個 (-) + + Click here, if you want to switch to another VST-plugin preset program. + Next (+) 下一個 (+) + Click here to select presets that are currently loaded in VST. + Save preset 保存預置 + Click here, if you want to save current VST-plugin preset program. 點擊這裏, 如果你想保存當前 VST-插件預設。 + + Effect by: + &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /> @@ -7314,173 +9278,217 @@ Please make sure you have read-permission to the file and the directory containi VstPlugin - Loading plugin - 載入插件 + + + The VST plugin %1 could not be loaded. + 無法載入VST插件 %1。 + Open Preset 打開預置 + + Vst Plugin Preset (*.fxp *.fxb) VST插件預置文件(*.fxp *.fxb) + : default : 默認 + " " + ' ' + Save Preset 保存預置 + .fxp .fxp + .FXP .FXP + .FXB .FXB + .fxb .fxb - Please wait while loading VST plugin... - 正在載入VST插件,請稍候…… + + Loading plugin + 載入插件 - The VST plugin %1 could not be loaded. - 無法載入VST插件 %1。 + + Please wait while loading VST plugin... + 正在載入VST插件,請稍候…… WatsynInstrument + Volume A1 + Volume A2 + Volume B1 + Volume B2 + Panning A1 + Panning A2 + Panning B1 + Panning B2 + Freq. multiplier A1 + Freq. multiplier A2 + Freq. multiplier B1 + Freq. multiplier B2 + Left detune A1 + Left detune A2 + Left detune B1 + Left detune B2 + Right detune A1 + Right detune A2 + Right detune B1 + Right detune B2 + A-B Mix + A-B Mix envelope amount + A-B Mix envelope attack + A-B Mix envelope hold + A-B Mix envelope decay + A1-B2 Crosstalk + A2-A1 modulation + B2-B1 modulation + Selected graph @@ -7488,213 +9496,291 @@ Please make sure you have read-permission to the file and the directory containi WatsynView - Select oscillator A1 - - - - Select oscillator A2 - - - - Select oscillator B1 - - - - Select oscillator B2 - - - - Mix output of A2 to A1 - - - - Modulate amplitude of A1 with output of A2 - - - - Ring-modulate A1 and A2 - - - - Modulate phase of A1 with output of A2 - - - - Mix output of B2 to B1 - - - - Modulate amplitude of B1 with output of B2 - - - - Ring-modulate B1 and B2 - - - - Modulate phase of B1 with output of B2 - - - - Draw your own waveform here by dragging your mouse on this graph. - - - - Load waveform - 載入波形 - - - Click to load a waveform from a sample file - - - - Phase left - - - - Click to shift phase by -15 degrees - - - - Phase right - - - - Click to shift phase by +15 degrees - - - - Normalize - 標準化 - - - Click to normalize - - - - Invert - 反轉 - - - Click to invert - - - - Smooth - 平滑 - - - Click to smooth - - - - Sine wave - 正弦波 - - - Click for sine wave - - - - Triangle wave - 三角波 - - - Click for triangle wave - - - - Click for saw wave - - - - Square wave - 方波 - - - Click for square wave - - - + + + + Volume 音量 + + + + Panning 聲相 + + + + Freq. multiplier + + + + Left detune + + + + + + + + cents + + + + Right detune + A-B Mix + Mix envelope amount + Mix envelope attack + Mix envelope hold + Mix envelope decay + Crosstalk + + + Select oscillator A1 + + + + + Select oscillator A2 + + + + + Select oscillator B1 + + + + + Select oscillator B2 + + + + + Mix output of A2 to A1 + + + + + Modulate amplitude of A1 with output of A2 + + + + + Ring-modulate A1 and A2 + + + + + Modulate phase of A1 with output of A2 + + + + + Mix output of B2 to B1 + + + + + Modulate amplitude of B1 with output of B2 + + + + + Ring-modulate B1 and B2 + + + + + Modulate phase of B1 with output of B2 + + + + + + + + Draw your own waveform here by dragging your mouse on this graph. + + + + + Load waveform + 載入波形 + + + + Click to load a waveform from a sample file + + + + + Phase left + + + + + Click to shift phase by -15 degrees + + + + + Phase right + + + + + Click to shift phase by +15 degrees + + + + + Normalize + 標準化 + + + + Click to normalize + + + + + Invert + 反轉 + + + + Click to invert + + + + + Smooth + 平滑 + + + + Click to smooth + + + + + Sine wave + 正弦波 + + + + Click for sine wave + + + + + + Triangle wave + 三角波 + + + + Click for triangle wave + + + + + Click for saw wave + + + + + Square wave + 方波 + + + + Click for square wave + + ZynAddSubFxInstrument + Portamento + Filter Frequency + Filter Resonance + Bandwidth 帶寬 + FM Gain FM 增益 + Resonance Center Frequency + Resonance Bandwidth + Forward MIDI Control Change Events @@ -7702,121 +9788,150 @@ Please make sure you have read-permission to the file and the directory containi ZynAddSubFxView - Show GUI - 顯示圖形界面 - - - Click here to show or hide the graphical user interface (GUI) of ZynAddSubFX. - - - + Portamento: + PORT + Filter Frequency: + FREQ 頻率 + Filter Resonance: + RES + Bandwidth: 帶寬: + BW + FM Gain: + FM GAIN + Resonance center frequency: + RES CF + Resonance bandwidth: + RES BW + Forward MIDI Control Changes + + + Show GUI + 顯示圖形界面 + + + + Click here to show or hide the graphical user interface (GUI) of ZynAddSubFX. + + audioFileProcessor + Amplify 增益 + Start of sample 採樣起始 + End of sample 採樣結尾 - Reverse sample - 反轉採樣 - - - Stutter - - - + Loopback point 循環點 + + Reverse sample + 反轉採樣 + + + Loop mode 循環模式 + + Stutter + + + + Interpolation mode 補間方式 + None + Linear 線性插補 + Sinc 辛格(Sinc)插補 + Sample not found: %1 採樣未找到: %1 @@ -7824,6 +9939,7 @@ Please make sure you have read-permission to the file and the directory containi bitInvader + Samplelength 採樣長度 @@ -7831,165 +9947,205 @@ Please make sure you have read-permission to the file and the directory containi bitInvaderView + Sample Length 採樣長度 - Sine wave - 正弦波 - - - Triangle wave - 三角波 - - - Saw wave - 鋸齒波 - - - Square wave - 方波 - - - White noise wave - 白噪音 - - - User defined wave - 用戶自定義波形 - - - Smooth - 平滑 - - - Click here to smooth waveform. - 點擊這裏平滑波形。 - - - Interpolation - - - - Normalize - 標準化 - - + Draw your own waveform here by dragging your mouse on this graph. + + Sine wave + 正弦波 + + + Click for a sine-wave. + + Triangle wave + 三角波 + + + Click here for a triangle-wave. 點擊這裡使用三角波。 + + Saw wave + 鋸齒波 + + + Click here for a saw-wave. + + Square wave + 方波 + + + Click here for a square-wave. 點擊這裡使用方形波。 + + White noise wave + 白噪音 + + + Click here for white-noise. + + User defined wave + 用戶自定義波形 + + + Click here for a user-defined shape. + + + Smooth + 平滑 + + + + Click here to smooth waveform. + 點擊這裏平滑波形。 + + + + Interpolation + + + + + Normalize + 標準化 + dynProcControlDialog + INPUT 輸入 + Input gain: 輸入增益: + OUTPUT 輸出 + Output gain: 輸出增益: + ATTACK + Peak attack time: + RELEASE + Peak release time: + Reset waveform 重置波形 + Click here to reset the wavegraph back to default + Smooth waveform 平滑波形 + Click here to apply smoothing to wavegraph 點擊這裏來使波形圖更爲平滑 + Increase wavegraph amplitude by 1dB + Click here to increase wavegraph amplitude by 1dB + Decrease wavegraph amplitude by 1dB + Click here to decrease wavegraph amplitude by 1dB + Stereomode Maximum + Process based on the maximum of both stereo channels + Stereomode Average + Process based on the average of both stereo channels + Stereomode Unlinked + Process each stereo channel independently @@ -7997,22 +10153,27 @@ Please make sure you have read-permission to the file and the directory containi dynProcControls + Input gain 輸入增益 + Output gain 輸出增益 + Attack time + Release time + Stereo mode @@ -8147,10 +10308,12 @@ Please make sure you have read-permission to the file and the directory containi fxLineLcdSpinBox + Assign to: 分配給: + New FX Channel 新的效果通道 @@ -8158,6 +10321,7 @@ Please make sure you have read-permission to the file and the directory containi graphModel + Graph 圖形 @@ -8165,50 +10329,62 @@ Please make sure you have read-permission to the file and the directory containi kickerInstrument + Start frequency 起始頻率 + End frequency 結束頻率 - Gain - 增益 - - + Length 長度 + Distortion Start 起始失真度 + Distortion End 結束失真度 + + Gain + 增益 + + + Envelope Slope 包絡線傾斜度 + Noise 噪音 + Click 力度 + Frequency Slope 頻率傾斜度 + Start from note 從哪個音符開始 + End to note 到哪個音符結束 @@ -8216,42 +10392,52 @@ Please make sure you have read-permission to the file and the directory containi kickerInstrumentView + Start frequency: 起始頻率: + End frequency: 結束頻率: - Gain: - 增益: - - + Frequency Slope: 頻率傾斜度: + + Gain: + 增益: + + + Envelope Length: 包絡長度: + Envelope Slope: 包絡線傾斜度: + Click: 力度: + Noise: 噪音: + Distortion Start: 起始失真度: + Distortion End: 結束失真度: @@ -8259,26 +10445,37 @@ Please make sure you have read-permission to the file and the directory containi ladspaBrowserView + + Available Effects 可用效果器 + + Unavailable Effects 不可用效果器 + + Instruments 樂器插件 + + Analysis Tools 分析工具 + + Don't know 未知 + This dialog displays information on all of the LADSPA plugins LMMS was able to locate. The plugins are divided into five categories based upon an interpretation of the port types and names. Available Effects are those that can be used by LMMS. In order for LMMS to be able to use an effect, it must, first and foremost, be an effect, which is to say, it has to have both input channels and output channels. LMMS identifies an input channel as an audio rate port containing 'in' in the name. Output channels are identified by the letters 'out'. Furthermore, the effect must have the same number of inputs and outputs and be real time capable. @@ -8307,6 +10504,7 @@ Double clicking any of the plugins will bring up information on the ports. + Type: 類型: @@ -8314,10 +10512,12 @@ Double clicking any of the plugins will bring up information on the ports. ladspaDescription + Plugins 插件 + Description 描述 @@ -8325,66 +10525,83 @@ Double clicking any of the plugins will bring up information on the ports. ladspaPortDialog + Ports + Name 名稱 + Rate + Direction 方向 + Type 類型 + Min < Default < Max 最小 < 默認 < 最大 + Logarithmic 對數 + SR Dependent + Audio 音頻 + Control 控制 + Input 輸入 + Output 輸出 + Toggled + Integer 整型 + Float 浮點 + + Yes @@ -8392,46 +10609,57 @@ Double clicking any of the plugins will bring up information on the ports. lb302Synth + VCF Cutoff Frequency + VCF Resonance + VCF Envelope Mod + VCF Envelope Decay + Distortion 失真 + Waveform 波形 + Slide Decay + Slide + Accent + Dead + 24dB/oct Filter @@ -8439,122 +10667,153 @@ Double clicking any of the plugins will bring up information on the ports. lb302SynthView + Cutoff Freq: + Resonance: 共鳴: + Env Mod: + Decay: 衰減: + 303-es-que, 24dB/octave, 3 pole filter + Slide Decay: + DIST: + Saw wave 鋸齒波 + Click here for a saw-wave. + Triangle wave 三角波 + Click here for a triangle-wave. 點擊這裡使用三角波。 + Square wave 方波 + Click here for a square-wave. 點擊這裡使用方形波。 + Rounded square wave + Click here for a square-wave with a rounded end. + Moog wave + Click here for a moog-like wave. + Sine wave 正弦波 + Click for a sine-wave. + + White noise wave 白噪音 + Click here for an exponential wave. + Click here for white-noise. + Bandlimited saw wave + Click here for bandlimited saw wave. + Bandlimited square wave + Click here for bandlimited square wave. + Bandlimited triangle wave + Click here for bandlimited triangle wave. + Bandlimited moog saw wave + Click here for bandlimited moog saw wave. @@ -8562,118 +10821,147 @@ Double clicking any of the plugins will bring up information on the ports. malletsInstrument + Hardness + Position + Vibrato Gain + Vibrato Freq + Stick Mix + Modulator + Crossfade + LFO Speed + LFO Depth + ADSR + Pressure + Motion + Speed + Bowed + Spread + Marimba + Vibraphone + Agogo + Wood1 + Reso + Wood2 + Beats + Two Fixed + Clump + Tubular Bells + Uniform Bar + Tuned Bar + Glass + Tibetan Bowl @@ -8681,149 +10969,186 @@ Double clicking any of the plugins will bring up information on the ports. malletsInstrumentView + Instrument + Spread + Spread: + + Missing files + 檔案遺失 + + + + Your Stk-installation seems to be incomplete. Please make sure the full Stk-package is installed! + + + + Hardness + Hardness: + Position + Position: + Vib Gain + Vib Gain: + Vib Freq + Vib Freq: + Stick Mix + Stick Mix: + Modulator + Modulator: + Crossfade + Crossfade: + LFO Speed + LFO Speed: + LFO Depth + LFO Depth: + ADSR + ADSR: + Pressure + Pressure: + Speed + Speed: - - Missing files - - - - Your Stk-installation seems to be incomplete. Please make sure the full Stk-package is installed! - - manageVSTEffectView + - VST parameter control - VST 參數控制 + VST Sync VST 同步 + Click here if you want to synchronize all parameters with VST plugin. 點擊這裏, 如果你想與 VST 插件同步所有參數。 + + Automated 自動 + Click here if you want to display automated parameters only. + Close 關閉 + Close VST effect knob-controller window. @@ -8831,30 +11156,39 @@ Double clicking any of the plugins will bring up information on the ports. manageVestigeInstrumentView + + - VST plugin control - VST插件控制 + VST Sync VST 同步 + Click here if you want to synchronize all parameters with VST plugin. 點擊這裏, 如果你想與 VST 插件同步所有參數。 + + Automated 自動 + Click here if you want to display automated parameters only. + Close 關閉 + Close VST plugin knob-controller window. @@ -8862,118 +11196,147 @@ Double clicking any of the plugins will bring up information on the ports. opl2instrument + Patch 音色 + Op 1 Attack + Op 1 Decay + Op 1 Sustain + Op 1 Release + Op 1 Level + Op 1 Level Scaling + Op 1 Frequency Multiple + Op 1 Feedback + Op 1 Key Scaling Rate + Op 1 Percussive Envelope + Op 1 Tremolo + Op 1 Vibrato + Op 1 Waveform + Op 2 Attack + Op 2 Decay + Op 2 Sustain + Op 2 Release + Op 2 Level + Op 2 Level Scaling + Op 2 Frequency Multiple + Op 2 Key Scaling Rate + Op 2 Percussive Envelope + Op 2 Tremolo + Op 2 Vibrato + Op 2 Waveform + FM + Vibrato Depth + Tremolo Depth @@ -8981,18 +11344,26 @@ Double clicking any of the plugins will bring up information on the ports. opl2instrumentView + + Attack 打進聲 + + Decay 衰減 + + Release 釋放 + + Frequency multiplier @@ -9000,10 +11371,12 @@ Double clicking any of the plugins will bring up information on the ports. organicInstrument + Distortion 失真 + Volume 音量 @@ -9011,50 +11384,63 @@ Double clicking any of the plugins will bring up information on the ports. organicInstrumentView + Distortion: 失真: - Volume: - 音量: - - - Randomise - 隨機 - - - Osc %1 waveform: - - - - Osc %1 volume: - - - - Osc %1 panning: - - - - cents - 音分 cents - - + The distortion knob adds distortion to the output of the instrument. + + Volume: + 音量: + + + The volume knob controls the volume of the output of the instrument. It is cumulative with the instrument window's volume control. + + Randomise + 隨機 + + + The randomize button randomizes all knobs except the harmonics,main volume and distortion knobs. + + + Osc %1 waveform: + + + + + Osc %1 volume: + + + + + Osc %1 panning: + + + + Osc %1 stereo detuning + + cents + 音分 cents + + + Osc %1 harmonic: @@ -9062,265 +11448,351 @@ Double clicking any of the plugins will bring up information on the ports. FreeBoyInstrument + Sweep time + Sweep direction + Sweep RtShift amount + + Wave Pattern Duty + Channel 1 volume + + + Volume sweep direction + + + Length of each step in sweep + Channel 2 volume + Channel 3 volume + Channel 4 volume + + Shift Register width + + + + Right Output level 右聲道輸出電平 + Left Output level + Channel 1 to SO2 (Left) + Channel 2 to SO2 (Left) + Channel 3 to SO2 (Left) + Channel 4 to SO2 (Left) + Channel 1 to SO1 (Right) + Channel 2 to SO1 (Right) + Channel 3 to SO1 (Right) + Channel 4 to SO1 (Right) + Treble + Bass 低音 - - Shift Register width - - FreeBoyInstrumentView + Sweep Time: + Sweep Time - Sweep RtShift amount: - - - - Sweep RtShift amount - - - - Wave pattern duty: - - - - Wave Pattern Duty - - - - Square Channel 1 Volume: - - - - Length of each step in sweep: - - - - Length of each step in sweep - - - - Wave pattern duty - - - - Square Channel 2 Volume: - - - - Square Channel 2 Volume - - - - Wave Channel Volume: - - - - Wave Channel Volume - - - - Noise Channel Volume: - - - - Noise Channel Volume - - - - SO1 Volume (Right): - - - - SO1 Volume (Right) - - - - SO2 Volume (Left): - - - - SO2 Volume (Left) - - - - Treble: - - - - Treble - - - - Bass: - - - - Bass - 低音 - - - Sweep Direction - - - - Volume Sweep Direction - - - - Shift Register Width - - - - Channel1 to SO1 (Right) - - - - Channel2 to SO1 (Right) - - - - Channel3 to SO1 (Right) - - - - Channel4 to SO1 (Right) - - - - Channel1 to SO2 (Left) - - - - Channel2 to SO2 (Left) - - - - Channel3 to SO2 (Left) - - - - Channel4 to SO2 (Left) - - - - Wave Pattern - - - + The amount of increase or decrease in frequency + + Sweep RtShift amount: + + + + + Sweep RtShift amount + + + + The rate at which increase or decrease in frequency occurs + + + Wave pattern duty: + + + + + Wave Pattern Duty + + + + + The duty cycle is the ratio of the duration (time) that a signal is ON versus the total period of the signal. + + + Square Channel 1 Volume: + + + + Square Channel 1 Volume + + + + Length of each step in sweep: + + + + + + + Length of each step in sweep + + + + + + The delay between step change + + Wave pattern duty + + + + + Square Channel 2 Volume: + + + + + + Square Channel 2 Volume + + + + + Wave Channel Volume: + + + + + + Wave Channel Volume + + + + + Noise Channel Volume: + + + + + + Noise Channel Volume + + + + + SO1 Volume (Right): + + + + + SO1 Volume (Right) + + + + + SO2 Volume (Left): + + + + + SO2 Volume (Left) + + + + + Treble: + + + + + Treble + + + + + Bass: + + + + + Bass + 低音 + + + + Sweep Direction + + + + + + + + + Volume Sweep Direction + + + + + Shift Register Width + + + + + Channel1 to SO1 (Right) + + + + + Channel2 to SO1 (Right) + + + + + Channel3 to SO1 (Right) + + + + + Channel4 to SO1 (Right) + + + + + Channel1 to SO2 (Left) + + + + + Channel2 to SO2 (Left) + + + + + Channel3 to SO2 (Left) + + + + + Channel4 to SO2 (Left) + + + + + Wave Pattern + + + + Draw the wave here @@ -9328,34 +11800,42 @@ Double clicking any of the plugins will bring up information on the ports. patchesDialog + Qsynth: Channel Preset Qsynth: 通道預設 + Bank selector 音色選擇器 + Bank + Program selector + Patch 音色 + Name 名稱 + OK 確定 + Cancel 取消 @@ -9363,187 +11843,232 @@ Double clicking any of the plugins will bring up information on the ports. pluginBrowser + no description 沒有描述 - Incomplete monophonic imitation tb303 + + A native amplifier plugin + 原生增益插件 + + + + Simple sampler with various settings for using samples (e.g. drums) in an instrument-track + 簡單地在樂器欄使用採樣(比如鼓音源), 同時也提供多種設置 + + + + Boost your bass the fast and simple way - Plugin for freely manipulating stereo output + + Customizable wavetable synthesizer + 可自定製的波表合成器 + + + + An oversampling bitcrusher - Plugin for controlling knobs with sound peaks + + Carla Patchbay Instrument + Carla Patchbay 樂器 + + + + Carla Rack Instrument + Carla Rack 樂器 + + + + A 4-band Crossover Equalizer - Plugin for enhancing stereo separation of a stereo input file + + A native delay plugin + 原生的衰減插件 + + + + A Dual filter plugin + + plugin for processing dynamics in a flexible way + + + + + A native eq plugin + 原生的 EQ 插件 + + + + A native flanger plugin + 一個原生的 鑲邊 (Flanger) 插件 + + + + Player for GIG files + 播放 GIG 檔案的播放器 + + + + Filter for importing Hydrogen files into LMMS + 匯入 Hydrogen 專案檔至 LMMS 的解析器 + + + + Versatile drum synthesizer + 多功能鼓合成器 + + + List installed LADSPA plugins 列出已安裝的 LADSPA 插件 - GUS-compatible patch instrument - GUS 兼容音色的樂器 - - - Additive Synthesizer for organ-like sounds - - - - Tuneful things to bang on - - - - VST-host for using VST(i)-plugins within LMMS - LMMS的VST(i)插件宿主 - - - Vibrating string modeler - - - + plugin for using arbitrary LADSPA-effects inside LMMS. 在 LMMS 中使用任意 LADSPA 效果的插件。 - Filter for importing MIDI-files into LMMS + + Incomplete monophonic imitation tb303 + + Filter for exporting MIDI-files from LMMS + 從 LMMS 匯出 MIDI 檔的解析器 + + + + Filter for importing MIDI-files into LMMS + 匯入 MIDI 檔至 LMMS 的解析器 + + + + Monstrous 3-oscillator synth with modulation matrix + + + + + A multitap echo delay plugin + + + + + A NES-like synthesizer + 類似於 NES 的合成器 + + + + 2-operator FM Synth + + + + + Additive Synthesizer for organ-like sounds + + + + + Emulation of GameBoy (TM) APU + GameBoy (TM) APU 模擬器 + + + + GUS-compatible patch instrument + GUS 兼容音色的樂器 + + + + Plugin for controlling knobs with sound peaks + + + + + Reverb algorithm by Sean Costello + + + + + Player for SoundFont files + 播放 SoundFont 檔案的播放器 + + + + LMMS port of sfxr + sfxr 的 LMMS 移植版本 + + + Emulation of the MOS6581 and MOS8580 SID. This chip was used in the Commodore 64 computer. 模擬 MOS6581 和 MOS8580 SID 的模擬器 這些芯片曾在 Commodore 64 電腦上用過。 - Player for SoundFont files - 在工程中使用SoundFont - - - Emulation of GameBoy (TM) APU - GameBoy (TM) APU 模擬器 - - - Customizable wavetable synthesizer - 可自定製的波表合成器 - - - Embedded ZynAddSubFX - 內置的 ZynAddSubFX - - - 2-operator FM Synth - - - - Filter for importing Hydrogen files into LMMS - 導入 Hydrogen 工程文件到 LMMS 的解析器 - - - LMMS port of sfxr - sfxr 的 LMMS 移植版本 - - - Monstrous 3-oscillator synth with modulation matrix - - - - Three powerful oscillators you can modulate in several ways - - - - A native amplifier plugin - 原生增益插件 - - - Carla Rack Instrument - Carla Rack 樂器 - - - 4-oscillator modulatable wavetable synth - - - - plugin for waveshaping - - - - Boost your bass the fast and simple way - - - - Versatile drum synthesizer - 多功能鼓合成器 - - - Simple sampler with various settings for using samples (e.g. drums) in an instrument-track - 簡單地在樂器欄使用採樣(比如鼓音源), 同時也提供多種設置 - - - plugin for processing dynamics in a flexible way - - - - Carla Patchbay Instrument - Carla Patchbay 樂器 - - - plugin for using arbitrary VST effects inside LMMS. - - - + Graphical spectrum analyzer plugin 圖形頻譜分析器插件 - A NES-like synthesizer - 類似於 NES 的合成器 + + Plugin for enhancing stereo separation of a stereo input file + 用以增強雙聲道輸入檔的聲道分離插件 - A native delay plugin - 原生的衰減插件 - - - Player for GIG files - 播放 GIG 文件的播放器 - - - A multitap echo delay plugin + + Plugin for freely manipulating stereo output - A native flanger plugin - 一個原生的 鑲邊 (Flanger) 插件 - - - An oversampling bitcrusher + + Tuneful things to bang on - A native eq plugin - 原生的 EQ 插件 - - - A 4-band Crossover Equalizer + + Three powerful oscillators you can modulate in several ways - A Dual filter plugin + + VST-host for using VST(i)-plugins within LMMS + LMMS的VST(i)插件宿主 + + + + Vibrating string modeler - Filter for exporting MIDI-files from LMMS + + plugin for using arbitrary VST effects inside LMMS. - Reverb algorithm by Sean Costello + + 4-oscillator modulatable wavetable synth + + + plugin for waveshaping + + + + + Embedded ZynAddSubFX + 內置的 ZynAddSubFX + Mathematical expression parser @@ -9552,58 +12077,72 @@ This chip was used in the Commodore 64 computer. sf2Instrument + Bank + Patch 音色 + Gain 增益 + Reverb 混響 + Reverb Roomsize 混響空間大小 + Reverb Damping 混響阻尼 + Reverb Width 混響寬度 + Reverb Level 混響級別 + Chorus 合唱 + Chorus Lines 合唱聲部 + Chorus Level 合唱電平 + Chorus Speed 合唱速度 + Chorus Depth 合唱深度 + A soundfont %1 could not be loaded. 無法載入Soundfont %1。 @@ -9611,74 +12150,92 @@ This chip was used in the Commodore 64 computer. sf2InstrumentView + Open other SoundFont file 打開其他SoundFont文件 + Click here to open another SF2 file 點擊此處打開另一個SF2文件 + Choose the patch 選擇路徑 + Gain 增益 + Apply reverb (if supported) 應用混響(如果支持) + This button enables the reverb effect. This is useful for cool effects, but only works on files that support it. 此按鈕會啓用混響效果器。可以製作出很酷的效果,但僅對支持的文件有效。 + Reverb Roomsize: 混響空間大小: + Reverb Damping: 混響阻尼: + Reverb Width: 混響寬度: + Reverb Level: 混響級別: + Apply chorus (if supported) 應用合唱 (如果支持) + This button enables the chorus effect. This is useful for cool echo effects, but only works on files that support it. 此按鈕會啓用合唱效果器。 + Chorus Lines: 合唱聲部: + Chorus Level: 合唱級別: + Chorus Speed: 合唱速度: + Chorus Depth: 合唱深度: + Open SoundFont file - 打開SoundFont文件 + 開啟 SoundFont 檔案 + SoundFont2 Files (*.sf2) SoundFont2 Files (*.sf2) @@ -9686,6 +12243,7 @@ This chip was used in the Commodore 64 computer. sfxrInstrument + Wave Form 波形 @@ -9693,26 +12251,32 @@ This chip was used in the Commodore 64 computer. sidInstrument + Cutoff 切除 + Resonance 共鳴 + Filter type 過濾器類型 + Voice 3 off 聲音 3 關 + Volume 音量 + Chip model 芯片型號 @@ -9720,134 +12284,172 @@ This chip was used in the Commodore 64 computer. sidInstrumentView + Volume: 音量: + Resonance: 共鳴: + + Cutoff frequency: 頻譜刀頻率: + High-Pass filter 高通濾波器 + Band-Pass filter 帶通濾波器 + Low-Pass filter 低通濾波器 + Voice3 Off 聲音 3 關 + MOS6581 SID MOS6581 SID + MOS8580 SID MOS8580 SID + + Attack: 打進聲: + Attack rate determines how rapidly the output of Voice %1 rises from zero to peak amplitude. + + Decay: 衰減: + Decay rate determines how rapidly the output falls from the peak amplitude to the selected Sustain level. + Sustain: 振幅持平: + Output of Voice %1 will remain at the selected Sustain amplitude as long as the note is held. + + Release: 聲音消失: + The output of of Voice %1 will fall from Sustain amplitude to zero amplitude at the selected Release rate. + + Pulse Width: + The Pulse Width resolution allows the width to be smoothly swept with no discernable stepping. The Pulse waveform on Oscillator %1 must be selected to have any audible effect. + Coarse: + The Coarse detuning allows to detune Voice %1 one octave up or down. + Pulse Wave + Triangle Wave + SawTooth + Noise 噪音 + Sync 同步 + Sync synchronizes the fundamental frequency of Oscillator %1 with the fundamental frequency of Oscillator %2 producing "Hard Sync" effects. + Ring-Mod + Ring-mod replaces the Triangle Waveform output of Oscillator %1 with a "Ring Modulated" combination of Oscillators %1 and %2. + Filtered + When Filtered is on, Voice %1 will be processed through the Filter. When Filtered is off, Voice %1 appears directly at the output, and the Filter has no effect on it. + Test 測試 + Test, when set, resets and locks Oscillator %1 at zero until Test is turned off. @@ -9855,10 +12457,12 @@ This chip was used in the Commodore 64 computer. stereoEnhancerControlDialog + WIDE + Width: 寬度: @@ -9866,6 +12470,7 @@ This chip was used in the Commodore 64 computer. stereoEnhancerControls + Width 寬度 @@ -9873,18 +12478,22 @@ This chip was used in the Commodore 64 computer. stereoMatrixControlDialog + Left to Left Vol: 從左到左音量: + Left to Right Vol: 從左到右音量: + Right to Left Vol: 從右到左音量: + Right to Right Vol: 從右到右音量: @@ -9892,18 +12501,22 @@ This chip was used in the Commodore 64 computer. stereoMatrixControls + Left to Left 從左到左 + Left to Right 從左到右 + Right to Left 從右到左 + Right to Right 從右到右 @@ -9911,10 +12524,12 @@ This chip was used in the Commodore 64 computer. vestigeInstrument + Loading plugin 載入插件 + Please wait while loading VST-plugin... 請等待VST插件加載完成... @@ -9922,42 +12537,52 @@ This chip was used in the Commodore 64 computer. vibed + String %1 volume + String %1 stiffness + Pick %1 position + Pickup %1 position + Pan %1 聲相 %1 + Detune %1 去諧 %1 + Fuzziness %1 模糊度 %1 + Length %1 長度 %1 + Impulse %1 + Octave %1 八度音 %1 @@ -9965,90 +12590,112 @@ This chip was used in the Commodore 64 computer. vibedView + Volume: 音量: + The 'V' knob sets the volume of the selected string. + String stiffness: + The 'S' knob sets the stiffness of the selected string. The stiffness of the string affects how long the string will ring out. The lower the setting, the longer the string will ring. + Pick position: + The 'P' knob sets the position where the selected string will be 'picked'. The lower the setting the closer the pick is to the bridge. + Pickup position: + The 'PU' knob sets the position where the vibrations will be monitored for the selected string. The lower the setting, the closer the pickup is to the bridge. + Pan: + The Pan knob determines the location of the selected string in the stereo field. + Detune: 去諧: + The Detune knob modifies the pitch of the selected string. Settings less than zero will cause the string to sound flat. Settings greater than zero will cause the string to sound sharp. + Fuzziness: + The Slap knob adds a bit of fuzz to the selected string which is most apparent during the attack, though it can also be used to make the string sound more 'metallic'. + Length: 長度: + The Length knob sets the length of the selected string. Longer strings will both ring longer and sound brighter, however, they will also eat up more CPU cycles. + Impulse or initial state + The 'Imp' selector determines whether the waveform in the graph is to be treated as an impulse imparted to the string by the pick or the initial state of the string. + Octave + The Octave selector is used to choose which harmonic of the note the string will ring at. For example, '-2' means the string will ring two octaves below the fundamental, 'F' means the string will ring at the fundamental, and '6' means the string will ring six octaves above the fundamental. + Impulse Editor + The waveform editor provides control over the initial state or impulse that is used to start the string vibrating. The buttons to the right of the graph will initialize the waveform to the selected type. The '?' button will load a waveform from a file--only the first 128 samples will be loaded. The waveform can also be drawn in the graph. @@ -10059,6 +12706,7 @@ The 'N' button will normalize the waveform. + Vibed models up to nine independently vibrating strings. The 'String' selector allows you to choose which string is being edited. The 'Imp' selector chooses whether the graph represents an impulse or the initial state of the string. The 'Octave' selector chooses which harmonic the string should vibrate at. The graph allows you to control the initial state or impulse used to set the string in motion. @@ -10073,129 +12721,160 @@ The LED in the lower right corner of the waveform editor determines whether the + Enable waveform 啓用波形 + Click here to enable/disable waveform. 點擊這裏啓用/禁用波形。 + String + The String selector is used to choose which string the controls are editing. A Vibed instrument can contain up to nine independently vibrating strings. The LED in the lower right corner of the waveform editor indicates whether the selected string is active. + Sine wave 正弦波 - Triangle wave - 三角波 - - - Saw wave - 鋸齒波 - - - Square wave - 方波 - - - White noise wave - 白噪音 - - - User defined wave - 用戶自定義波形 - - - Smooth - 平滑 - - - Click here to smooth waveform. - 點擊這裏平滑波形。 - - - Normalize - 標準化 - - - Click here to normalize waveform. - 點擊這裏標準化波形。 - - + Use a sine-wave for current oscillator. 爲當前振盪器使用正弦波。 + + Triangle wave + 三角波 + + + Use a triangle-wave for current oscillator. 爲當前振盪器使用三角波。 + + Saw wave + 鋸齒波 + + + Use a saw-wave for current oscillator. 爲當前振盪器使用鋸齒波。 + + Square wave + 方波 + + + Use a square-wave for current oscillator. 爲當前振盪器使用方波。 + + White noise wave + 白噪音 + + + Use white-noise for current oscillator. 爲當前振盪器使用白噪音。 + + User defined wave + 用戶自定義波形 + + + Use a user-defined waveform for current oscillator. 爲當前振盪器使用用戶自定波形。 + + + Smooth + 平滑 + + + + Click here to smooth waveform. + 點擊這裏平滑波形。 + + + + Normalize + 標準化 + + + + Click here to normalize waveform. + 點擊這裏標準化波形。 + voiceObject + Voice %1 pulse width + Voice %1 attack + Voice %1 decay + Voice %1 sustain + Voice %1 release + Voice %1 coarse detuning + Voice %1 wave shape 聲音 %1 波形形狀 + Voice %1 sync 聲音 %1 同步 + Voice %1 ring modulate + Voice %1 filtered + Voice %1 test 聲音 %1 測試 @@ -10203,58 +12882,72 @@ The LED in the lower right corner of the waveform editor determines whether the waveShaperControlDialog + INPUT 輸入 + Input gain: 輸入增益: + OUTPUT 輸出 + Output gain: 輸出增益: + Reset waveform 重置波形 + Click here to reset the wavegraph back to default + Smooth waveform 平滑波形 + Click here to apply smoothing to wavegraph 點擊這裏來使波形圖更爲平滑 + Increase graph amplitude by 1dB + Click here to increase wavegraph amplitude by 1dB + Decrease graph amplitude by 1dB + Click here to decrease wavegraph amplitude by 1dB + Clip input 輸入壓限 + Clip input signal to 0dB 將輸入信號限制到 0dB @@ -10262,12 +12955,14 @@ The LED in the lower right corner of the waveform editor determines whether the waveShaperControls + Input gain 輸入增益 + Output gain 輸出增益 - \ No newline at end of file + diff --git a/data/presets/X-Pressive/Ambition.xpf b/data/presets/X-Pressive/Ambition.xpf deleted file mode 100644 index 2d93f7c05..000000000 --- a/data/presets/X-Pressive/Ambition.xpf +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/data/presets/X-Pressive/Baby Violin.xpf b/data/presets/X-Pressive/Baby Violin.xpf deleted file mode 100644 index 2e887d3d2..000000000 --- a/data/presets/X-Pressive/Baby Violin.xpf +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/data/presets/X-Pressive/Bad Singer.xpf b/data/presets/X-Pressive/Bad Singer.xpf deleted file mode 100644 index ca9cfd5a3..000000000 --- a/data/presets/X-Pressive/Bad Singer.xpf +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/data/presets/X-Pressive/Cloud Bass.xpf b/data/presets/X-Pressive/Cloud Bass.xpf deleted file mode 100644 index 4e444f22a..000000000 --- a/data/presets/X-Pressive/Cloud Bass.xpf +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/data/presets/X-Pressive/Creature.xpf b/data/presets/X-Pressive/Creature.xpf deleted file mode 100644 index b667a9c7f..000000000 --- a/data/presets/X-Pressive/Creature.xpf +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/data/presets/X-Pressive/Electric Shock.xpf b/data/presets/X-Pressive/Electric Shock.xpf deleted file mode 100644 index 7dea6fe4a..000000000 --- a/data/presets/X-Pressive/Electric Shock.xpf +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/data/presets/X-Pressive/Faded Colors.xpf b/data/presets/X-Pressive/Faded Colors.xpf deleted file mode 100644 index 84a37826a..000000000 --- a/data/presets/X-Pressive/Faded Colors.xpf +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/data/presets/X-Pressive/Fat Flute.xpf b/data/presets/X-Pressive/Fat Flute.xpf deleted file mode 100644 index 92242114e..000000000 --- a/data/presets/X-Pressive/Fat Flute.xpf +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/data/presets/X-Pressive/Horn.xpf b/data/presets/X-Pressive/Horn.xpf deleted file mode 100644 index 099480569..000000000 --- a/data/presets/X-Pressive/Horn.xpf +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/data/presets/X-Pressive/Piano-Gong.xpf b/data/presets/X-Pressive/Piano-Gong.xpf deleted file mode 100644 index 241f61a55..000000000 --- a/data/presets/X-Pressive/Piano-Gong.xpf +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/data/presets/X-Pressive/Rubber Bass.xpf b/data/presets/X-Pressive/Rubber Bass.xpf deleted file mode 100644 index 73c3648ba..000000000 --- a/data/presets/X-Pressive/Rubber Bass.xpf +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/data/presets/X-Pressive/Space Echoes.xpf b/data/presets/X-Pressive/Space Echoes.xpf deleted file mode 100644 index 1d4d2b543..000000000 --- a/data/presets/X-Pressive/Space Echoes.xpf +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/data/presets/X-Pressive/Speaker Swapper.xpf b/data/presets/X-Pressive/Speaker Swapper.xpf deleted file mode 100644 index cf80b9304..000000000 --- a/data/presets/X-Pressive/Speaker Swapper.xpf +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/data/presets/X-Pressive/Toss.xpf b/data/presets/X-Pressive/Toss.xpf deleted file mode 100644 index 27a0b3f96..000000000 --- a/data/presets/X-Pressive/Toss.xpf +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/data/presets/X-Pressive/Untuned Bell.xpf b/data/presets/X-Pressive/Untuned Bell.xpf deleted file mode 100644 index 744927063..000000000 --- a/data/presets/X-Pressive/Untuned Bell.xpf +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/data/presets/X-Pressive/Vibrato.xpf b/data/presets/X-Pressive/Vibrato.xpf deleted file mode 100644 index 34795de11..000000000 --- a/data/presets/X-Pressive/Vibrato.xpf +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/data/presets/X-Pressive/X-Distorted.xpf b/data/presets/X-Pressive/X-Distorted.xpf deleted file mode 100644 index cbe3742a5..000000000 --- a/data/presets/X-Pressive/X-Distorted.xpf +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/data/presets/X-Pressive/Accordion.xpf b/data/presets/Xpressive/Accordion.xpf similarity index 100% rename from data/presets/X-Pressive/Accordion.xpf rename to data/presets/Xpressive/Accordion.xpf diff --git a/data/presets/Xpressive/Ambition.xpf b/data/presets/Xpressive/Ambition.xpf new file mode 100644 index 000000000..dd6448977 --- /dev/null +++ b/data/presets/Xpressive/Ambition.xpf @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/presets/Xpressive/Baby Violin.xpf b/data/presets/Xpressive/Baby Violin.xpf new file mode 100644 index 000000000..45e407fc8 --- /dev/null +++ b/data/presets/Xpressive/Baby Violin.xpf @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/presets/Xpressive/Bad Singer.xpf b/data/presets/Xpressive/Bad Singer.xpf new file mode 100644 index 000000000..10fe3b308 --- /dev/null +++ b/data/presets/Xpressive/Bad Singer.xpf @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/presets/Xpressive/Cloud Bass.xpf b/data/presets/Xpressive/Cloud Bass.xpf new file mode 100644 index 000000000..15bf4188d --- /dev/null +++ b/data/presets/Xpressive/Cloud Bass.xpf @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/presets/Xpressive/Creature.xpf b/data/presets/Xpressive/Creature.xpf new file mode 100644 index 000000000..bee39f224 --- /dev/null +++ b/data/presets/Xpressive/Creature.xpf @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/presets/X-Pressive/Dream.xpf b/data/presets/Xpressive/Dream.xpf similarity index 100% rename from data/presets/X-Pressive/Dream.xpf rename to data/presets/Xpressive/Dream.xpf diff --git a/data/presets/Xpressive/Electric Shock.xpf b/data/presets/Xpressive/Electric Shock.xpf new file mode 100644 index 000000000..3f9aef104 --- /dev/null +++ b/data/presets/Xpressive/Electric Shock.xpf @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/presets/Xpressive/Faded Colors - notes test.xpf b/data/presets/Xpressive/Faded Colors - notes test.xpf new file mode 100644 index 000000000..de4938f4d --- /dev/null +++ b/data/presets/Xpressive/Faded Colors - notes test.xpf @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/presets/Xpressive/Faded Colors.xpf b/data/presets/Xpressive/Faded Colors.xpf new file mode 100644 index 000000000..a514ee438 --- /dev/null +++ b/data/presets/Xpressive/Faded Colors.xpf @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/presets/Xpressive/Fat Flute.xpf b/data/presets/Xpressive/Fat Flute.xpf new file mode 100644 index 000000000..76d9e2f84 --- /dev/null +++ b/data/presets/Xpressive/Fat Flute.xpf @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/presets/X-Pressive/Frog.xpf b/data/presets/Xpressive/Frog.xpf similarity index 100% rename from data/presets/X-Pressive/Frog.xpf rename to data/presets/Xpressive/Frog.xpf diff --git a/data/presets/Xpressive/Horn.xpf b/data/presets/Xpressive/Horn.xpf new file mode 100644 index 000000000..d44b332b2 --- /dev/null +++ b/data/presets/Xpressive/Horn.xpf @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/presets/X-Pressive/Low Battery.xpf b/data/presets/Xpressive/Low Battery.xpf similarity index 64% rename from data/presets/X-Pressive/Low Battery.xpf rename to data/presets/Xpressive/Low Battery.xpf index c0e648ac9..78f1fc78f 100644 --- a/data/presets/X-Pressive/Low Battery.xpf +++ b/data/presets/Xpressive/Low Battery.xpf @@ -1,20 +1,21 @@ - + - - + + - + + + - - - - + + + + - - - + + diff --git a/data/presets/Xpressive/Piano-Gong.xpf b/data/presets/Xpressive/Piano-Gong.xpf new file mode 100644 index 000000000..a8244b799 --- /dev/null +++ b/data/presets/Xpressive/Piano-Gong.xpf @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/presets/Xpressive/Rubber Bass.xpf b/data/presets/Xpressive/Rubber Bass.xpf new file mode 100644 index 000000000..4b1409e22 --- /dev/null +++ b/data/presets/Xpressive/Rubber Bass.xpf @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/presets/Xpressive/Space Echoes.xpf b/data/presets/Xpressive/Space Echoes.xpf new file mode 100644 index 000000000..be6de3653 --- /dev/null +++ b/data/presets/Xpressive/Space Echoes.xpf @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/presets/Xpressive/Speaker Swapper.xpf b/data/presets/Xpressive/Speaker Swapper.xpf new file mode 100644 index 000000000..d4da5aa2f --- /dev/null +++ b/data/presets/Xpressive/Speaker Swapper.xpf @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/presets/Xpressive/Toss.xpf b/data/presets/Xpressive/Toss.xpf new file mode 100644 index 000000000..387e78fd9 --- /dev/null +++ b/data/presets/Xpressive/Toss.xpf @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/presets/Xpressive/Untuned Bell.xpf b/data/presets/Xpressive/Untuned Bell.xpf new file mode 100644 index 000000000..5dd61ec18 --- /dev/null +++ b/data/presets/Xpressive/Untuned Bell.xpf @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/presets/Xpressive/Vibrato.xpf b/data/presets/Xpressive/Vibrato.xpf new file mode 100644 index 000000000..a7dda25e9 --- /dev/null +++ b/data/presets/Xpressive/Vibrato.xpf @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/presets/Xpressive/X-Distorted.xpf b/data/presets/Xpressive/X-Distorted.xpf new file mode 100644 index 000000000..b42495d75 --- /dev/null +++ b/data/presets/Xpressive/X-Distorted.xpf @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/projects/demos/CapDan/CapDan-TwilightArea-OriginalByAlf42red.mmpz b/data/projects/demos/CapDan/CapDan-TwilightArea-OriginalByAlf42red.mmpz index 1687e8c34..b4a00e1ea 100644 Binary files a/data/projects/demos/CapDan/CapDan-TwilightArea-OriginalByAlf42red.mmpz and b/data/projects/demos/CapDan/CapDan-TwilightArea-OriginalByAlf42red.mmpz differ diff --git a/data/projects/demos/CapDan/CapDan-ZeroSumGame-OriginalByZakarra.mmpz b/data/projects/demos/CapDan/CapDan-ZeroSumGame-OriginalByZakarra.mmpz index 95a29daff..578c4f926 100644 Binary files a/data/projects/demos/CapDan/CapDan-ZeroSumGame-OriginalByZakarra.mmpz and b/data/projects/demos/CapDan/CapDan-ZeroSumGame-OriginalByZakarra.mmpz differ diff --git a/data/projects/demos/CapDan/LICENSES.TXT b/data/projects/demos/CapDan/LICENSES.TXT new file mode 100644 index 000000000..6a640decd --- /dev/null +++ b/data/projects/demos/CapDan/LICENSES.TXT @@ -0,0 +1,15 @@ +* CapDan-ReggaeTry.mmpz + - Artistic 2.0 + - https://lmms.io/lsp/index.php?action=show&file=1369 + +* CapDan-ReggaetonTry.mmpz + - Artistic 2.0 + - https://lmms.io/lsp/index.php?action=show&file=1370 + +* CapDan-TwilightArea-OriginalByAlf42red.mmpz + - CC (by-sa) + - https://lmms.io/lsp/index.php?action=show&file=1439 + +* CapDan-ZeroSumGame-OriginalByZakarra.mmpz + - Artistic 2.0 + - https://lmms.io/lsp/index.php?action=show&file=1565 diff --git a/data/projects/demos/EsoXLB-CPU.mmpz b/data/projects/demos/EsoXLB-CPU.mmpz index 1c2549027..bc2445e87 100644 Binary files a/data/projects/demos/EsoXLB-CPU.mmpz and b/data/projects/demos/EsoXLB-CPU.mmpz differ diff --git a/data/projects/demos/Greippi - Krem Kaakkuja (Second Flight Remix).mmpz b/data/projects/demos/Greippi - Krem Kaakkuja (Second Flight Remix).mmpz index 2f862dd51..6c9f34369 100644 Binary files a/data/projects/demos/Greippi - Krem Kaakkuja (Second Flight Remix).mmpz and b/data/projects/demos/Greippi - Krem Kaakkuja (Second Flight Remix).mmpz differ diff --git a/data/projects/demos/Impulslogik-Zen.mmpz b/data/projects/demos/Impulslogik-Zen.mmpz index 05fa375c4..774ce89e3 100644 Binary files a/data/projects/demos/Impulslogik-Zen.mmpz and b/data/projects/demos/Impulslogik-Zen.mmpz differ diff --git a/data/projects/demos/Jousboxx-BuzzerBeater.mmpz b/data/projects/demos/Jousboxx-BuzzerBeater.mmpz index 60795608c..59f0d63f6 100644 Binary files a/data/projects/demos/Jousboxx-BuzzerBeater.mmpz and b/data/projects/demos/Jousboxx-BuzzerBeater.mmpz differ diff --git a/data/projects/demos/LICENSES.TXT b/data/projects/demos/LICENSES.TXT index c33cc02c8..399d7909f 100644 --- a/data/projects/demos/LICENSES.TXT +++ b/data/projects/demos/LICENSES.TXT @@ -2,22 +2,6 @@ - CC (by-sa) - https://lmms.io/lsp/index.php?action=show&file=819 -* CapDan-ReggaeTry.mmpz - - Artistic 2.0 - - https://lmms.io/lsp/index.php?action=show&file=1369 - -* CapDan-ReggaetonTry.mmpz - - Artistic 2.0 - - https://lmms.io/lsp/index.php?action=show&file=1370 - -* CapDan-TwilightArea-OriginalByAlf42red.mmpz - - CC (by-sa) - - https://lmms.io/lsp/index.php?action=show&file=1439 - -* CapDan-ZeroSumGame-OriginalByZakarra.mmpz - - Artistic 2.0 - - https://lmms.io/lsp/index.php?action=show&file=1565 - * EsoXLB-CPU.mmpz - Artistic 2.0 - https://lmms.io/lsp/index.php?action=show&file=723 @@ -34,6 +18,10 @@ - Artistic 2.0 - https://lmms.io/lsp/index.php?action=show&file=581 +* Jousboxx-BuzzerBeater.mmpz + - CC BY-SA 4.0 + - https://github.com/LMMS/lmms/pull/3482#issuecomment-293609866 + * Momo64-esp.mmpz - Artistic 2.0 - https://lmms.io/lsp/index.php?action=show&file=1534 @@ -50,6 +38,10 @@ - Artistic 2.0 - https://lmms.io/lsp/index.php?action=show&file=1156 +* Popsip-Electric Dancer.mmpz + - Creative Commons (by-nc) + - https://lmms.io/lsp/?action=show&file=5414 + * Root84-Initialize.mmpz - Yellow openmusic - https://lmms.io/lsp/index.php?action=show&file=628 @@ -62,14 +54,6 @@ - Artistic 2.0 - https://lmms.io/lsp/index.php?action=show&file=515 -* Skiessi-C64.mmpz - - CC (by sa) - - https://lmms.io/lsp/index.php?action=show&file=472 - -* Skiessi-Onion.mmpz - - CC (by-sa) - - https://lmms.io/lsp/index.php?action=show&file=405 - * Socceroos-Progress.mmpz - Artistic 2.0 - https://lmms.io/lsp/index.php?action=show&file=1516 @@ -78,6 +62,10 @@ - Artistic 2.0 - https://lmms.io/lsp/index.php?action=show&file=1060 +* Thaledric-Armageddon.mmpz + - Creative Commons (by-nc-sa) + - https://lmms.io/lsp/?action=show&file=1947 + * Thomasso-AxeFromThe80s.mmpz - Artistic 2.0 - https://lmms.io/lsp/index.php?action=show&file=474 @@ -85,7 +73,3 @@ * unfa-Spoken.mmpz - CC (by-nc) - https://lmms.io/lsp/index.php?action=show&file=4929 - -* Jousboxx-BuzzerBeater.mmpz - - CC (by-sa) - - https://lmms.io/lsp/?action=show&file=10488 diff --git a/data/projects/demos/Momo64-esp.mmpz b/data/projects/demos/Momo64-esp.mmpz index 68ae6822c..37d1a52b5 100644 Binary files a/data/projects/demos/Momo64-esp.mmpz and b/data/projects/demos/Momo64-esp.mmpz differ diff --git a/data/projects/demos/Namitryus-K-Project.mmpz b/data/projects/demos/Namitryus-K-Project.mmpz index 6d463cbb9..4d62826c9 100644 Binary files a/data/projects/demos/Namitryus-K-Project.mmpz and b/data/projects/demos/Namitryus-K-Project.mmpz differ diff --git a/data/projects/demos/Oglsdl-Dr8v2.mmpz b/data/projects/demos/Oglsdl-Dr8v2.mmpz index eb9d7559a..14b1b0e85 100644 Binary files a/data/projects/demos/Oglsdl-Dr8v2.mmpz and b/data/projects/demos/Oglsdl-Dr8v2.mmpz differ diff --git a/data/projects/demos/Oglsdl-PpTrip.mmpz b/data/projects/demos/Oglsdl-PpTrip.mmpz index d1baceeba..776aeea2b 100644 Binary files a/data/projects/demos/Oglsdl-PpTrip.mmpz and b/data/projects/demos/Oglsdl-PpTrip.mmpz differ diff --git a/data/projects/demos/Popsip-Electric Dancer.mmpz b/data/projects/demos/Popsip-Electric Dancer.mmpz index fc93dd64a..1c935dbe1 100644 Binary files a/data/projects/demos/Popsip-Electric Dancer.mmpz and b/data/projects/demos/Popsip-Electric Dancer.mmpz differ diff --git a/data/projects/demos/Root84-Initialize.mmpz b/data/projects/demos/Root84-Initialize.mmpz index 349fcb88f..05200823a 100644 Binary files a/data/projects/demos/Root84-Initialize.mmpz and b/data/projects/demos/Root84-Initialize.mmpz differ diff --git a/data/projects/demos/Saber-FinalStep.mmpz b/data/projects/demos/Saber-FinalStep.mmpz index 5e3d1d1ff..05a5022a7 100644 Binary files a/data/projects/demos/Saber-FinalStep.mmpz and b/data/projects/demos/Saber-FinalStep.mmpz differ diff --git a/data/projects/demos/Settel-InnerRecreation.mmpz b/data/projects/demos/Settel-InnerRecreation.mmpz index aaa01e0bc..78e1d611d 100644 Binary files a/data/projects/demos/Settel-InnerRecreation.mmpz and b/data/projects/demos/Settel-InnerRecreation.mmpz differ diff --git a/data/projects/demos/Shovon-ProgressiveHousePluckDemo.mmpz b/data/projects/demos/Shovon-ProgressiveHousePluckDemo.mmpz index 2d31bd7bd..3ec6a2cff 100644 Binary files a/data/projects/demos/Shovon-ProgressiveHousePluckDemo.mmpz and b/data/projects/demos/Shovon-ProgressiveHousePluckDemo.mmpz differ diff --git a/data/projects/demos/Skiessi/LICENSES.TXT b/data/projects/demos/Skiessi/LICENSES.TXT new file mode 100644 index 000000000..8cb4adc86 --- /dev/null +++ b/data/projects/demos/Skiessi/LICENSES.TXT @@ -0,0 +1,7 @@ +* Skiessi-C64.mmpz + - CC (by sa) + - https://lmms.io/lsp/index.php?action=show&file=472 + +* Skiessi-Onion.mmpz + - CC (by-sa) + - https://lmms.io/lsp/index.php?action=show&file=405 diff --git a/data/projects/demos/Skiessi/Skiessi-C64.mmpz b/data/projects/demos/Skiessi/Skiessi-C64.mmpz index f0b3f5cdb..a9756453b 100644 Binary files a/data/projects/demos/Skiessi/Skiessi-C64.mmpz and b/data/projects/demos/Skiessi/Skiessi-C64.mmpz differ diff --git a/data/projects/demos/Skiessi/Skiessi-Onion.mmpz b/data/projects/demos/Skiessi/Skiessi-Onion.mmpz index 0c40fb60a..23a1ddc48 100644 Binary files a/data/projects/demos/Skiessi/Skiessi-Onion.mmpz and b/data/projects/demos/Skiessi/Skiessi-Onion.mmpz differ diff --git a/data/projects/demos/Skiessi/Skiessi-RandomProjectNumber14253.mmpz b/data/projects/demos/Skiessi/Skiessi-RandomProjectNumber14253.mmpz index d3c6e0f8d..bc2810567 100644 Binary files a/data/projects/demos/Skiessi/Skiessi-RandomProjectNumber14253.mmpz and b/data/projects/demos/Skiessi/Skiessi-RandomProjectNumber14253.mmpz differ diff --git a/data/projects/demos/Skiessi/Skiessi-TurningPoint.mmpz b/data/projects/demos/Skiessi/Skiessi-TurningPoint.mmpz index ee5be4b55..47a0a3672 100644 Binary files a/data/projects/demos/Skiessi/Skiessi-TurningPoint.mmpz and b/data/projects/demos/Skiessi/Skiessi-TurningPoint.mmpz differ diff --git a/data/projects/demos/Socceroos-Progress.mmpz b/data/projects/demos/Socceroos-Progress.mmpz index 74ff5774c..854663787 100644 Binary files a/data/projects/demos/Socceroos-Progress.mmpz and b/data/projects/demos/Socceroos-Progress.mmpz differ diff --git a/data/projects/demos/TameAnderson-MakeMe.mmpz b/data/projects/demos/TameAnderson-MakeMe.mmpz index de0152818..b69a64e3a 100644 Binary files a/data/projects/demos/TameAnderson-MakeMe.mmpz and b/data/projects/demos/TameAnderson-MakeMe.mmpz differ diff --git a/data/projects/demos/Thaledric-Armageddon.mmpz b/data/projects/demos/Thaledric-Armageddon.mmpz index 0e9d5f83f..731ea55f7 100644 Binary files a/data/projects/demos/Thaledric-Armageddon.mmpz and b/data/projects/demos/Thaledric-Armageddon.mmpz differ diff --git a/data/projects/demos/Thomasso-AxeFromThe80s.mmpz b/data/projects/demos/Thomasso-AxeFromThe80s.mmpz index af68b8b8b..f7056d38c 100644 Binary files a/data/projects/demos/Thomasso-AxeFromThe80s.mmpz and b/data/projects/demos/Thomasso-AxeFromThe80s.mmpz differ diff --git a/data/projects/demos/TobyDox-Psycho.mmpz b/data/projects/demos/TobyDox-Psycho.mmpz index 09ec6b6a6..c4fe7a1c4 100644 Binary files a/data/projects/demos/TobyDox-Psycho.mmpz and b/data/projects/demos/TobyDox-Psycho.mmpz differ diff --git a/data/projects/demos/unfa-Spoken.mmpz b/data/projects/demos/unfa-Spoken.mmpz index 659afa03a..66b7589d1 100644 Binary files a/data/projects/demos/unfa-Spoken.mmpz and b/data/projects/demos/unfa-Spoken.mmpz differ diff --git a/data/projects/shorties/DirtyLove.mmpz b/data/projects/shorties/DirtyLove.mmpz index 177c05ce5..37b766f4d 100644 Binary files a/data/projects/shorties/DirtyLove.mmpz and b/data/projects/shorties/DirtyLove.mmpz differ diff --git a/data/projects/shorties/LICENSES.TXT b/data/projects/shorties/LICENSES.TXT index bba2b5547..47969a984 100644 --- a/data/projects/shorties/LICENSES.TXT +++ b/data/projects/shorties/LICENSES.TXT @@ -1,3 +1,11 @@ +* Crunk(Demo).mmp + - Artistic 2.0 + - https://lmms.io/lsp/?action=show&file=4093 + +* DirtyLove.mmpz + - CC-BY-SA + - https://github.com/LMMS/lmms/pull/2727 + * Greshz-CoolSnip.mmpz - Artistic 2.0 - https://lmms.io/lsp/index.php?action=show&file=1170 diff --git a/data/projects/shorties/Root84-TrancyLoop.mmpz b/data/projects/shorties/Root84-TrancyLoop.mmpz index 22bd5f2fa..f5eb032ac 100644 Binary files a/data/projects/shorties/Root84-TrancyLoop.mmpz and b/data/projects/shorties/Root84-TrancyLoop.mmpz differ diff --git a/data/projects/shorties/Skiessi-222.mmpz b/data/projects/shorties/Skiessi-222.mmpz index a56833645..a7076949c 100644 Binary files a/data/projects/shorties/Skiessi-222.mmpz and b/data/projects/shorties/Skiessi-222.mmpz differ diff --git a/data/projects/shorties/Surrender-Main.mmpz b/data/projects/shorties/Surrender-Main.mmpz index a94df2497..556581170 100644 Binary files a/data/projects/shorties/Surrender-Main.mmpz and b/data/projects/shorties/Surrender-Main.mmpz differ diff --git a/data/projects/shorties/sv-DnB-Startup.mmpz b/data/projects/shorties/sv-DnB-Startup.mmpz index c9d8d5970..db32d3452 100644 Binary files a/data/projects/shorties/sv-DnB-Startup.mmpz and b/data/projects/shorties/sv-DnB-Startup.mmpz differ diff --git a/data/projects/shorties/sv-Trance-Startup.mmpz b/data/projects/shorties/sv-Trance-Startup.mmpz index c508b1500..bea731461 100644 Binary files a/data/projects/shorties/sv-Trance-Startup.mmpz and b/data/projects/shorties/sv-Trance-Startup.mmpz differ diff --git a/data/themes/classic/clear_ghost_note.png b/data/themes/classic/clear_ghost_note.png new file mode 100644 index 000000000..c9f85a2b4 Binary files /dev/null and b/data/themes/classic/clear_ghost_note.png differ diff --git a/data/themes/classic/ghost_note.png b/data/themes/classic/ghost_note.png new file mode 100644 index 000000000..532245e11 Binary files /dev/null and b/data/themes/classic/ghost_note.png differ diff --git a/data/themes/classic/icon_small.png b/data/themes/classic/icon_small.png new file mode 100644 index 000000000..522290061 Binary files /dev/null and b/data/themes/classic/icon_small.png differ diff --git a/data/themes/classic/proportional_snap.png b/data/themes/classic/proportional_snap.png new file mode 100644 index 000000000..66a0bb049 Binary files /dev/null and b/data/themes/classic/proportional_snap.png differ diff --git a/data/themes/classic/record_step_off.png b/data/themes/classic/record_step_off.png new file mode 100644 index 000000000..8da17a910 Binary files /dev/null and b/data/themes/classic/record_step_off.png differ diff --git a/data/themes/classic/record_step_on.png b/data/themes/classic/record_step_on.png new file mode 100644 index 000000000..700ba97f3 Binary files /dev/null and b/data/themes/classic/record_step_on.png differ diff --git a/data/themes/classic/style.css b/data/themes/classic/style.css index 1cf9375bc..97d68f6e3 100644 --- a/data/themes/classic/style.css +++ b/data/themes/classic/style.css @@ -123,9 +123,14 @@ PianoRoll { qproperty-backgroundShade: rgba( 255, 255, 255, 10 ); qproperty-noteModeColor: rgb( 255, 255, 255 ); qproperty-noteColor: rgb( 119, 199, 216 ); + qproperty-noteTextColor: rgb( 255, 255, 255 ); qproperty-noteOpacity: 128; qproperty-noteBorders: true; /* boolean property, set false to have borderless notes */ qproperty-selectedNoteColor: rgb( 0, 125, 255 ); + qproperty-ghostNoteColor: #000000; + qproperty-ghostNoteTextColor: #ffffff; + qproperty-ghostNoteOpacity: 50; + qproperty-ghostNoteBorders: true; qproperty-barColor: #4afd85; qproperty-markedSemitoneColor: rgba( 0, 255, 200, 60 ); /* Grid colors */ @@ -157,6 +162,9 @@ GroupBox { VisualizationWidget { background: none; border: none; + qproperty-normalColor: rgb(71, 253, 133); + qproperty-warningColor: rgb(255, 192, 64); + qproperty-clippingColor: rgb(255, 64, 64); } /* main toolbar cpu load widget - this can have transparent bg now */ @@ -889,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/clear_ghost_note.png b/data/themes/default/clear_ghost_note.png new file mode 100644 index 000000000..c9f85a2b4 Binary files /dev/null and b/data/themes/default/clear_ghost_note.png differ diff --git a/data/themes/default/ghost_note.png b/data/themes/default/ghost_note.png new file mode 100644 index 000000000..073442659 Binary files /dev/null and b/data/themes/default/ghost_note.png differ diff --git a/data/themes/default/icon.png b/data/themes/default/icon.png index ae9fe6a2a..ec881aacf 100644 Binary files a/data/themes/default/icon.png and b/data/themes/default/icon.png differ diff --git a/data/themes/default/icon_small.png b/data/themes/default/icon_small.png new file mode 100644 index 000000000..fd74011f9 Binary files /dev/null and b/data/themes/default/icon_small.png differ diff --git a/data/themes/default/proportional_snap.png b/data/themes/default/proportional_snap.png new file mode 100644 index 000000000..66a0bb049 Binary files /dev/null and b/data/themes/default/proportional_snap.png differ diff --git a/data/themes/default/record_step_off.png b/data/themes/default/record_step_off.png new file mode 100644 index 000000000..8da17a910 Binary files /dev/null and b/data/themes/default/record_step_off.png differ diff --git a/data/themes/default/record_step_on.png b/data/themes/default/record_step_on.png new file mode 100644 index 000000000..700ba97f3 Binary files /dev/null and b/data/themes/default/record_step_on.png differ diff --git a/data/themes/default/splash.png b/data/themes/default/splash.png index f95733e95..74f9fdef4 100644 Binary files a/data/themes/default/splash.png and b/data/themes/default/splash.png differ diff --git a/data/themes/default/style.css b/data/themes/default/style.css index a4a31ab6b..f95469201 100644 --- a/data/themes/default/style.css +++ b/data/themes/default/style.css @@ -9,16 +9,23 @@ QLabel, QTreeWidget, QListWidget, QGroupBox, QMenuBar { QTreeView { outline: none; + font-size: 12px; +} + +QTreeWidget::item { + padding: 1px; } QTreeWidget::item:hover, QTreeWidget::branch:hover { background-color: #3C444E; + padding-left: 0px; } QTreeWidget::item:selected, QTreeWidget::branch:selected { background-color: #17793b; + padding-left: 0px; } QTreeView::branch:has-children:open { @@ -81,6 +88,12 @@ TextFloat { } +/* splash screen text */ +QSplashScreen QLabel { + color: white; +} + + QMenu { border-top: 2px solid #08993E; background-color: #15191c; @@ -142,9 +155,14 @@ PianoRoll { qproperty-backgroundShade: rgba(255, 255, 255, 10); qproperty-noteModeColor: #0bd556; qproperty-noteColor: #0bd556; + qproperty-noteTextColor: #ffffff; qproperty-noteOpacity: 165; qproperty-noteBorders: false; /* boolean property, set false to have borderless notes */ qproperty-selectedNoteColor: #064d79; + qproperty-ghostNoteColor: #000000; + qproperty-ghostNoteTextColor: #ffffff; + qproperty-ghostNoteOpacity: 50; + qproperty-ghostNoteBorders: false; qproperty-barColor: #078f3a; qproperty-markedSemitoneColor: rgba(255, 255, 255, 30); /* Grid colors */ @@ -176,6 +194,9 @@ GroupBox { VisualizationWidget { background: none; border: none; + qproperty-normalColor: rgb(71, 253, 133); + qproperty-warningColor: rgb(255, 192, 64); + qproperty-clippingColor: rgb(255, 64, 64); } /* main toolbar cpu load widget - this can have transparent bg now */ @@ -912,7 +933,4 @@ LmmsPalette { qproperty-brightText: #d1d8e4; qproperty-highlight: #262b30; qproperty-highlightedText: #d1d8e4; - /* the next two are used for whatsthis dialogs */ - qproperty-toolTipText: #d1d8e4; - qproperty-toolTipBase: #101213; } diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 000000000..86f03c427 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,382 @@ +lmms (@VERSION@) unstable; urgency=low + + * Upstream integration. + * Drop Debian menu entry (policy 9.6). + + -- Javier Serrano Polo Sat, 03 Nov 2018 02:43:42 +0100 + +lmms (1.1.3-8) unstable; urgency=low + + * Fix build (Closes: #897806). + * Allow recommendations (Closes: #891756). + + -- Javier Serrano Polo Sat, 13 Oct 2018 17:05:54 +0200 + +lmms (1.1.3-7.1) unstable; urgency=high + + * Non-maintainer upload. + + [ Javier Serrano Polo ] + * Fix build with Clang. + * Fix build with GCC 7 (Closes: #853527). + + [ Boyuan Yang ] + * Remove Patrick Winnertz from uploaders list. (Closes: #867759) + Thank you for your previous contributions! + + -- Boyuan Yang <073plan@gmail.com> Sat, 10 Mar 2018 11:32:05 +0800 + +lmms (1.1.3-7) unstable; urgency=low + + [ Javier Serrano Polo ] + * Separate flags for WINE_BUILD_FLAGS to fix build problem on i386. + + -- Petter Reinholdtsen Mon, 26 Dec 2016 07:36:54 +0000 + +lmms (1.1.3-6) unstable; urgency=low + + [ Javier Serrano Polo ] + * Build with install RUNPATH (reproducibility). + + -- Petter Reinholdtsen Sun, 25 Dec 2016 09:38:53 +0000 + +lmms (1.1.3-5) unstable; urgency=medium + + [ Javier Serrano Polo ] + * Add Wine stable path to PATH, otherwise wine package would be required. + * Sort plug-in embedded resources (reproducibility). + * Define NDEBUG instead of setting build type to honor optimization choice. + + -- Javier Serrano Polo Sat, 03 Sep 2016 17:31:05 +0200 + +lmms (1.1.3-4) unstable; urgency=medium + + [ Javier Serrano Polo ] + * Sort lists generated from globbing expressions (reproducibility). + * Fixed upgrade that installs recommended packages (Closes: #827039). + * Dropped unused build dependencies. + * Dropped workaround for #824715, wineg++ is fixed. + * Added contributors. + * Honor CONTRIBUTORS override. + * Replace __FILE__ (reproducibility). + * Use build type "Release" (reproducibility). + + -- Javier Serrano Polo Wed, 08 Jun 2016 01:25:37 +0200 + +lmms (1.1.3-3) unstable; urgency=medium + + [ Javier Serrano Polo ] + * Dropped Wine path from PATH. + * Fixed lmms-common upgrade (Closes: #825287). + * Hide vocoder plug-in, it is now in swh-plugins (Closes: #826110). + * Added workaround for #824715 (Closes: #825286). + + -- Petter Reinholdtsen Fri, 03 Jun 2016 08:51:31 +0000 + +lmms (1.1.3-2) unstable; urgency=medium + + [ Javier Serrano Polo ] + * Enabled vst plugin on i386 and amd64 (Closes: #763720). + * Made Calf and vocoder plugins available to other programs (Closes: #758888). + * Fixed version of metalish_dong01.ogg (Closes: #802588). + * Bumped Standards-Version to 3.9.7. Doxygen documentation is not very useful. + * Upgraded to Standards-Version 3.9.8. Ship icons in the default hicolor icon + theme directories. + * Use presets from zynaddsubfx-data. + * Fixed build problems with GCC 6 (Closes: #811697). + * Switch to PulseAudio back end on likely ALSA interception (Closes: #781479). + * Updated copyright information. + * Removed non-free projects. + + -- Petter Reinholdtsen Wed, 18 May 2016 09:09:23 +0000 + +lmms (1.1.3-1) unstable; urgency=low + + * New upstream version 1.1.3 (Closes: #788457). + - Drop well-defined-loop.patch, included upstream. + * Add config for git-buildpackage to use pristine-tar all the time. + * Change homepage url to new http://lmms.io/. + * Added fluid as build-depend. + * New patch find-fluid.patch to find the fluid binary in unstable. + * New patch gcc5.patch to get the code building with gcc 5 in + unstable (Closes: #777989). + * Added man-page-adjustment.patch to fix manpage formatting of AUTHOR + block. Discovered thanks to lintian. + + -- Petter Reinholdtsen Mon, 21 Sep 2015 13:54:02 +0200 + +lmms (1.0.3-5) unstable; urgency=low + + * Make lmms replace and break lmms-common (<< 1.0.0-1) to handle the + fact that /usr/share/menu/lmms moved from lmms-common to lmms in + this version (Closes: #765970). + + -- Petter Reinholdtsen Sun, 19 Oct 2014 23:43:08 +0200 + +lmms (1.0.3-4) unstable; urgency=low + + * Correct watch file to reflect '-src' part of upstream tarball. + * New desktop-argument.patch to let desktops know how to pass files to + lmms. Thanks to lintian for noticing the bug. + * Revert change to enable the vsl plugin in version 1.0.3-3, as it did + not work. Reopen bug #763720. + + -- Petter Reinholdtsen Wed, 08 Oct 2014 19:21:53 +0200 + +lmms (1.0.3-3) unstable; urgency=medium + + * Try to get vsl plugin working on i386 by build depending on libwine-dev + and wine32-dev-tools (Closes: #763720). Unable to get it working on + amd64. + + -- Petter Reinholdtsen Tue, 07 Oct 2014 12:13:16 +0200 + +lmms (1.0.3-2) unstable; urgency=medium + + * Change build rule to only enable ALSA support on Linux (Closes: #754718). + Patch from Steven Chamberlain with input from Guillem Jover. + * Drop libwine-dev build dependency to avoid build failure in the + vst plugin. It should be enabled when we figure out how to do it. + + -- Petter Reinholdtsen Thu, 02 Oct 2014 08:19:53 +0200 + +lmms (1.0.3-1) unstable; urgency=low + + * Move package into Debian Edu git repository and add myself as + co-maintainer. + * Update to upstream version 1.0.3. + * Correct build dependency on i386, use libwine-dev instead of the now + obsolete wine-dev (Closes: #748183). + * Update Standards-Version from 3.9.5 to 3.9.6. + * Add new well-defined-loop.patch to fix compile error triggered by + undefined loop behaviour (Closes: #753177). + + -- Petter Reinholdtsen Wed, 01 Oct 2014 23:00:19 +0200 + +lmms (1.0.0-1) unstable; urgency=low + + * New upstream version (Closes: #703900, #735764, #696271) + * Using a wraped-style control (Closes: #689347) + * Don't suggest vcf as it no longer exists (since a long time) + (Closes: #618350) + * Problems with jack backend were fixed long ago (Closes: #557421) + * No depends/recommends on wine anymore (Closes: #622215, #622080) + + -- Patrick Winnertz Thu, 24 Apr 2014 22:30:17 +0200 + +lmms (0.4.10-2.3) unstable; urgency=low + + * Non maintainer upload. + * Remove wine-related dependencies on amd64, thereby disabling building + VST plugin. (Closes: #676760) + + -- Hilko Bengen Wed, 27 Jun 2012 23:14:40 +0200 + +lmms (0.4.10-2.2) unstable; urgency=low + + * Non maintainer upload. + * Fix build failure with GCC 4.7. Closes: #667265. + * Turn on verbose build. + + -- Matthias Klose Tue, 17 Apr 2012 14:08:53 +0200 + +lmms (0.4.10-2.1) unstable; urgency=low + + * Non-maintainer upload. + * Fix FTBFS on GNU/kFreeBSD. Thanks Pino Toscano. (Closes: #641064) + + -- Robert Millan Fri, 27 Apr 2012 22:55:55 +0200 + +lmms (0.4.10-2) unstable; urgency=low + + * Removed build-dep on libestools2.0-dev (Closes: #614975) + + -- Patrick Winnertz Fri, 11 Mar 2011 09:37:43 +0100 + +lmms (0.4.10-1) unstable; urgency=low + + * Imported Upstream version 0.4.10 + * changed mode of patch + * Add source/format with 3.0 (quilt) and rearrange source a bit + * Bump standarts version to 3.9.1 - no further changes needed + + -- Patrick Winnertz Fri, 11 Feb 2011 20:03:06 +0100 + +lmms (0.4.7-2) unstable; urgency=low + + [ Reinhard Tartler ] + * Depend on wine only on i386 and amd64 (Closes: #590950) + + [ Patrick Winnertz ] + * Uploading patch from siretart, thanks for helping. + + -- Patrick Winnertz Mon, 02 Aug 2010 10:13:28 +0200 + +lmms (0.4.7-1) unstable; urgency=low + + * New upstream version + + -- Patrick Winnertz Thu, 29 Jul 2010 16:24:00 +0200 + +lmms (0.4.6-2) unstable; urgency=low + + * Build-depend on libestools2.0-dev (Closes: #589882) + + -- Patrick Winnertz Wed, 28 Jul 2010 11:55:16 +0200 + +lmms (0.4.6-1) unstable; urgency=low + + * New upstream version (Closes: #565733) + * Bumped standards version to 3.8.3, no further changes needed + + -- Patrick Winnertz Sun, 24 Jan 2010 16:40:39 +0100 + +lmms (0.4.5-1) unstable; urgency=low + + * New upstream version (Closes: #543645) + * Fix FTBFS on amd64 (Closes: #540671 #543017) + + -- Patrick Winnertz Fri, 11 Sep 2009 09:56:45 +0200 + +lmms (0.4.4-1) unstable; urgency=low + + * New upstream version (Closes: #511363) + * Provide menu file (Closes: #514905) + - The menufile is included in lmms-common and not in lmms + as it is not arch specific + * Bumped standards version to 3.8.2 no further changes needed + + -- Patrick Winnertz Wed, 05 Aug 2009 20:46:40 +0200 + +lmms (0.3.2-1) unstable; urgency=low + + * Decrease wine dependency to wine-bin as suggested. (Closes: #446163) + * Acknowlegded NMU from Pierre Habouzit in order to + fix FTBFS with gcc-4.3 which (Closes: #462202) + * Now including the singerbot plugin. (Closes: #443224) + * Add patch to prevent lmms from crashing. + + -- Patrick Winnertz Mon, 17 Mar 2008 10:56:12 +0100 + +lmms (0.3.1-1.1) unstable; urgency=low + + * Non-maintainer upload. + * Add g++-4.3.patch to fix g++-4.3 FTBFS (Closes: 462202). + + -- Pierre Habouzit Sun, 16 Mar 2008 23:21:56 +0000 + +lmms (0.3.1-1) unstable; urgency=low + + * Packaging new upstream release. + * Install Upstream Changelog (Closes: #441477) + Thanks to Felipe Sateler + * Lowered the caps dependency to Recommends (Closes: #446163) + * Added -i/-a to the build targets in rules in order to make sure that only + (in)dep packages are build. + * Changed my maintainer address + * Added patch to remove stereo_enhancer plugin which has a ftbfs with gcc + 4.2.3 + * Added imagemagick as build-dep since we have to convert a .png to a .xpm + via convert + * Doesn't install upstreams menu file, since it's outdated.. instead use + our own. + * Standard-Version bump to 3.7.3 + * Remove Homepage field from Description and create a own Header + * Added postinst and postrm for lmms-common to call update-menu if available + (this has to be done manually, since we doesn't use dh_installmenu to install + the menu file) + + -- Patrick Winnertz Thu, 06 Dec 2007 07:08:04 +0100 + +lmms (0.3.0-1) unstable; urgency=low + + [ Tobias Doerffel ] + * New upstream release. (Closes: #439301) + * Removed patch from Thomas Girard as upstream merged changes + + [ Patrick Winnertz ] + * Moved manpage into correct package (lmms) + * Removed manuall installation of Upstream Changelog, thanks to the power of + debhelper ;-) + * FTBFS with gcc 4.2 is fixed by upstream (Closes: #383295) + * lmms has now a proper menu entry (Closes: #383406) + * lmms depends now on the same version of lmms-common (Closes: #389037) + * fixed by upstream: arpeggio status is now saved (Closes: #433262) + * Added build-depends libqt3-i18n (Closes: #384406) + * Added watch file for lmms (Closes: #439302) + Thanks to Raphael Geissert + * Improved copyright file + * Doesn't build libsingerbot since it is experimental and doesn't work + correct yet + * Added several build-dependencys (libstk0-dev, libestools1.2-dev, ladspa-sdk, + libflac-dev, libwine-dev [i386], libqt3-i18n, libasound2-dev, + festival-dev, dpatch ) + * Take over this package from Florian Ragwitz, so set myself as maintainer + * Add a depends on a specific version of lmms-common + * Added several new dependencys to lmms + * Improved description of lmms and lmms-common + * Die on errors of clean, but don't die if the makefile doesn't exist + * Added watch file + + -- Patrick Winnertz Fri, 24 Aug 2007 08:23:34 +0200 + +lmms (0.2.1-1.1) unstable; urgency=high + + * Non-maintainer Upload + * Add Patch by Thomas Girard for segfault right after + lmms starting up (Closes: 382491) + + -- Michael Ablassmeier Tue, 5 Sep 2006 12:00:40 +0200 + +lmms (0.2.1-1) unstable; urgency=low + + * New upstream release. + * Bump up Standards-Version to 3.7.2 (no changes). + * Use DH_COMPAT 5. + + -- Florian Ragwitz Sun, 13 Aug 2006 14:40:13 +0200 + +lmms (0.1.4-1) unstable; urgency=low + + * New upstream release. + + -- Florian Ragwitz Sat, 4 Feb 2006 07:16:47 +0100 + +lmms (0.1.3-1) unstable; urgency=low + + * New upstream release. + * debian/lmms.1 was included by upstream. Removed it from debian/. + * Install lmms.1 in lmms-common instead of lmms to safe some mirror space. + * Added a lintian override for the above, as lintian is not smart enough to + check for manpages in other packages from the same source package on which + a package with a missing manpage depends. + + -- Florian Ragwitz Wed, 1 Feb 2006 18:28:42 +0100 + +lmms (0.1.2-1) unstable; urgency=low + + * New upstream release. + + -- Florian Ragwitz Thu, 22 Dec 2005 16:22:50 +0100 + +lmms (0.1.1-2) unstable; urgency=low + + * lmms-common doesn't depend on lmms anymore to remove a circular + dependencies (Closes: #339906). + + -- Florian Ragwitz Sun, 20 Nov 2005 12:27:08 +0100 + +lmms (0.1.1-1) unstable; urgency=low + + * New upstream release. + * Changed Maintainer address. + * Added libjack-dev to Build-Depends. + + -- Florian Ragwitz Mon, 31 Oct 2005 10:48:36 +0100 + +lmms (0.0.9+0.1.0rc1-1) unstable; urgency=low + + * Initial Release (Closes: #315976). + + -- Florian Ragwitz Fri, 22 Jul 2005 16:33:17 +0200 + diff --git a/debian/compat b/debian/compat new file mode 100644 index 000000000..ec635144f --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +9 diff --git a/debian/control b/debian/control new file mode 100644 index 000000000..880e0d89a --- /dev/null +++ b/debian/control @@ -0,0 +1,125 @@ +Source: lmms +Section: sound +Priority: optional +Maintainer: Debian Edu Packaging Team +Uploaders: + Petter Reinholdtsen , + Israel Dahl , + Javier Serrano Polo , +Build-Depends: + cmake, + debhelper (>= 9.0.0), + fluid, + ladspa-sdk, + libasound2-dev [linux-any], + libfftw3-dev, + libfltk1.3-dev, + libfluidsynth-dev, + libgig-dev, + libjack-jackd2-dev, + liblist-moreutils-perl, + libmp3lame-dev, + libpulse-dev, + libqt5x11extras5-dev, + libsamplerate0-dev, + libsdl1.2-dev, + libsndfile1-dev, + libsndio-dev, + libsoundio-dev, + libstk0-dev, + libvorbis-dev, + libxcb-keysyms1-dev, + libxcb-util0-dev, + libxml-perl, + libxml2-utils, + portaudio19-dev, + qtbase5-private-dev, + qttools5-dev, + wine64-tools [amd64] | wine32-tools [i386] +Standards-Version: 4.2.1.4 +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: + caps, + lmms-vst-server:i386 (>= ${source:Version}), + 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 +Description: Linux Multimedia Studio - minimal installation + 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 + producing music with your computer by creating cool loops, synthesizing and + mixing sounds, arranging samples, having more fun with your MIDI-keyboard + and much more... + . + LMMS combines the features of a tracker-/sequencer-program (pattern-/channel-/ + sample-/song-/effect-management) and those of powerful synthesizers and + samplers in a modern, user-friendly and easy to use graphical user-interface. + . + This package provides the minimal installation. + +Package: lmms +Architecture: any +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 + producing music with your computer by creating cool loops, synthesizing and + mixing sounds, arranging samples, having more fun with your MIDI-keyboard + and much more... + . + LMMS combines the features of a tracker-/sequencer-program (pattern-/channel-/ + sample-/song-/effect-management) and those of powerful synthesizers and + samplers in a modern, user-friendly and easy to use graphical user-interface. + . + This package provides the recommended installation. + +Package: lmms-common +Architecture: all +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- + source) programs like FruityLoops, Cubase and Logic giving you the ability of + producing music with your computer by creating cool loops, synthesizing and + mixing sounds, arranging samples, having more fun with your MIDI-keyboard + and much more... + . + LMMS combines the features of a tracker-/sequencer-program (pattern-/channel-/ + sample-/song-/effect-management) and those of powerful synthesizers and + samplers in a modern, user-friendly and easy to use graphical user-interface. + . + This package contains the platform independent files such as samples, presets + and some example projects. + +Package: lmms-vst-server +Architecture: amd64 i386 +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 new file mode 100644 index 000000000..01b30459e --- /dev/null +++ b/debian/copyright @@ -0,0 +1,1373 @@ +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 +Comment: + This package was debianized by Florian Ragwitz on + Thu, 14 Apr 2005 13:24:57 +0200. + +Files: * +Copyright: + 1998-2000 Paul Kellett (mda-vst.com) + 1999-2004 Dag Lem + 2002 Kjetil S. Matheussen + 2003-2007 Rui Nuno Capela + 2003-2005 Shay Green + 2004-2014 Tobias Doerffel + 2004 Paul Davis + 2004 Torben Hohn + 2005-2008 Danny McRae + 2006-2008 Andreas Brandmaier + 2006-2008 Javier Serrano Polo + 2007-2014 Vesa Kivimäki + 2007-2013 Paul Giblock + 2007 Keith Marshall + 2008-2009 Andrew Kelley + 2008 Attila Herman + 2008 Csaba Hruska + 2013-2014 Raine M. Ekman + 2013 Mike Choi + 2014 David French + 2014 Hannu Haahti + 2014 Lukas Wohlschläger + 2014 Rubén Ibarra Pastor + 2014 Simon Symeonidis + 2014 Wong Cho Ching + Chrissy McManus + Gabriel + Gurjot Singh + Johannes Lorenz + Jonathan Aquilina + Jorrit Rouwe + Juan Fabián Simón + LocoMatt + Oskar Wallgren + Peter Hanappe + Sebastian Tilsch + Tobiasz Karoń (unfa) + Uroš Maravić +License: GPL-2+ + +Files: data/projects/demos/Alf42red-* + data/projects/demos/CapDan/CapDan-TwilightArea-* +Copyright: + 2010-2011 Armin Heller + 2011 Der Daniel (CapDan) +License: CC-BY-SA-3 + +Files: data/projects/demos/AngryLlama-* + data/projects/demos/Ashore.* + data/projects/demos/DnB.* + data/projects/demos/Farbro-* + data/projects/demos/Greippi* + data/projects/demos/Namitryus-* + data/projects/demos/Popsip-* + data/projects/demos/Root84-* + data/projects/demos/Shovon-* + data/projects/demos/Skiessi/* + data/projects/demos/StrictProduction-* + data/projects/demos/Thaledric-* + data/projects/demos/TobyDox-* + data/projects/demos/unfa-* + data/projects/shorties/DirtyLove.* + data/projects/shorties/Root84-* + data/projects/shorties/Skiessi-* + data/projects/shorties/sv-* +Copyright: + LMMS contributors +License: non-free + +Files: data/projects/demos/CapDan/CapDan-ReggaeTry.* + data/projects/demos/CapDan/CapDan-ReggaetonTry.* + data/projects/demos/CapDan/CapDan-ZeroSumGame-* + data/projects/demos/EsoXLB-* + data/projects/demos/Impulslogik-* + data/projects/demos/Momo64-* + data/projects/demos/Oglsdl-* + data/projects/demos/Settel-* + data/projects/demos/Socceroos-* + data/projects/demos/TameAnderson-* + data/projects/demos/Thomasso-* + data/projects/shorties/Crunk* + data/projects/shorties/Greshz-* + data/projects/shorties/Surrender-* +Copyright: + 2009 Achim Settelmeier + 2009 Peter Asplund (Surrender) + 2009 Thomasso + 2010 E.SoX (lowbudget) + 2010 Impulslogik + 2011 Der Daniel (CapDan) + 2011 Sam (socceroos) + 2011 mauro (momo64) + 2011 tame anderson + 2011 Ümit (oglsdl) + Greshz +License: Artistic-2 + +Files: data/projects/demos/Jousboxx-* +Copyright: + Jousboxx +License: CC-BY-SA-4 + +Files: data/projects/CoolSongs/Saber-* +Copyright: + Saber Rastikerdar +License: BSD-2-clause + +Files: include/ladspa.h +Copyright: + 2000-2002 Paul Barton-Davis + 2000-2002 Richard W.E. Furse + 2000-2002 Stefan Westerfeld +License: LGPL-2.1+ + +Files: plugins/LadspaEffect/calf/* +Copyright: + 2001-2010 Krzysztof Foltman + 2001-2010 Markus Schmidt + 2001-2010 Thor Harald Johansen + Alexandre Prokoudine + Carl Hetherington + Christian Holschuh + Damien Zammit + Dave Robillard + David Täht + Hans Baier + Hermann Meyer + Thorsten Wilms + Tom Szilagyi + Torben Hohn +License: LGPL-2+ +Comment: + COPYING is the GNU Lesser General Public License. Headers refer to version 2 of + this license instead of version 2.1. + +Files: plugins/LadspaEffect/calf/src/calf/vumeter.h +Copyright: + 2007 Krzysztof Foltman +License: GPL-2+ + +Files: plugins/LadspaEffect/caps/* +Copyright: + 1998 Robert Bristow-Johnson + 2001-2011 Tim Goetze + 2003-2009 David Yeh + 2004-2005 Steve Harris +License: GPL-2+ + +Files: plugins/LadspaEffect/cmt/* +Copyright: + 1998 Andy Sloane + 1999-2001 David A. Bartold + 2000-2002 Richard W.E. Furse + 2000 Jezar + 2002 Nathaniel Virgo +License: GPL-2+ + +Files: plugins/LadspaEffect/swh/* +Copyright: + 1999 Juhana Sadeharju + 2000-2003 Alexander Ehlert + 2000-2002 Steve Harris + Andy Wingo + Frank Neumann + Jesse Chappell + Joern Nettingsmeier + Marcus Andersson + Mark Knecht + Matthias Nagorni + Nathaniel Virgo + Pascal Haakmat + Patrick Shirkey + Paul Winkler +License: GPL-2+ + +Files: plugins/LadspaEffect/swh/gsm/* +Copyright: + 1992-1994 Carsten Bormann + 1992-1994 Jutta Degener +License: Bormann-Degener + +Files: plugins/LadspaEffect/swh/util/pitchscale.c +Copyright: + 1999 Stephan M. Sprenger +License: WOL + +Files: plugins/LadspaEffect/swh/vocoder_1337.c +Copyright: + Achim Settelmeier + Hexasoft + Josh Green +License: GPL-2+ + +Files: plugins/LadspaEffect/tap/* +Copyright: + 2004 Tom Szilagyi + Alexander Koenig +License: GPL-2+ + +Files: plugins/MidiImport/portsmf/* +Copyright: + 1999-2000 Phil Burk + 1999-2000 Ross Bencina + 2001-2006 Roger B. Dannenberg +License: Expat +Comment: + The Expat license constitutes the entire Portsmf license; however, + the PortMusic community also makes the following non-binding requests: + . + Any person wishing to distribute modifications to the Software is + requested to send the modifications to the original developer so that + they can be incorporated into the canonical version. It is also + requested that these non-binding requests be included along with the + license above. + +Files: plugins/opl2/fmopl.* + plugins/opl2/mididata.h + plugins/opl2/opl.h + plugins/opl2/temuopl.* +Copyright: + 1999-2007 Simon Peter + 1999-2000 Tatsuyuki Satoh +License: LGPL-2.1+ + +Files: plugins/sfxr/readme.* + plugins/sfxr/sfxr.* +Copyright: + 2007 Tomas Pettersson + 2014 Wong Cho Ching +License: Expat and GPL-2+ + +Files: plugins/zynaddsubfx/zynaddsubfx/* +Copyright: + 2002-2009 Nasca Octavian Paul + 2009-2010 Mark McCurry + 2009 Alan Calvert + 2012 Jonathan Liles + Achim Settelmeier + Alexis Ballier + Andre Sklenar + Christopher Oliver + Damien Goutte-Gattat + Daniel Clemente + Emmanuel Saracco + Filipe Coelho + Gerald Folcher + Hans Petter Selasky + Harald Hvaal + Ilario Glasgo + James Morris + Johannes Lorenz + Jérémie Andréi + Lars Luthman + Lieven Moors + Olaf Schulz + Ryan Billing + Stephen Parry + Tobias Doerffel +License: GPL-2+ + +License: Artistic-2 + The Artistic License 2.0 + . + Copyright (c) 2000-2006, The Perl Foundation. + . + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + . + Preamble + . + This license establishes the terms under which a given free software + Package may be copied, modified, distributed, and/or redistributed. + The intent is that the Copyright Holder maintains some artistic + control over the development of that Package while still keeping the + Package available as open source and free software. + . + You are always permitted to make arrangements wholly outside of this + license directly with the Copyright Holder of a given Package. If the + terms of this license do not permit the full use that you propose to + make of the Package, you should contact the Copyright Holder and seek + a different licensing arrangement. + . + Definitions + . + "Copyright Holder" means the individual(s) or organization(s) + named in the copyright notice for the entire Package. + . + "Contributor" means any party that has contributed code or other + material to the Package, in accordance with the Copyright Holder's + procedures. + . + "You" and "your" means any person who would like to copy, + distribute, or modify the Package. + . + "Package" means the collection of files distributed by the + Copyright Holder, and derivatives of that collection and/or of + those files. A given Package may consist of either the Standard + Version, or a Modified Version. + . + "Distribute" means providing a copy of the Package or making it + accessible to anyone else, or in the case of a company or + organization, to others outside of your company or organization. + . + "Distributor Fee" means any fee that you charge for Distributing + this Package or providing support for this Package to another + party. It does not mean licensing fees. + . + "Standard Version" refers to the Package if it has not been + modified, or has been modified only in ways explicitly requested + by the Copyright Holder. + . + "Modified Version" means the Package, if it has been changed, and + such changes were not explicitly requested by the Copyright + Holder. + . + "Original License" means this Artistic License as Distributed with + the Standard Version of the Package, in its current version or as + it may be modified by The Perl Foundation in the future. + . + "Source" form means the source code, documentation source, and + configuration files for the Package. + . + "Compiled" form means the compiled bytecode, object code, binary, + or any other form resulting from mechanical transformation or + translation of the Source form. + . + Permission for Use and Modification Without Distribution + . + (1) You are permitted to use the Standard Version and create and use + Modified Versions for any purpose without restriction, provided that + you do not Distribute the Modified Version. + . + Permissions for Redistribution of the Standard Version + . + (2) You may Distribute verbatim copies of the Source form of the + Standard Version of this Package in any medium without restriction, + either gratis or for a Distributor Fee, provided that you duplicate + all of the original copyright notices and associated disclaimers. At + your discretion, such verbatim copies may or may not include a + Compiled form of the Package. + . + (3) You may apply any bug fixes, portability changes, and other + modifications made available from the Copyright Holder. The resulting + Package will still be considered the Standard Version, and as such + will be subject to the Original License. + . + Distribution of Modified Versions of the Package as Source + . + (4) You may Distribute your Modified Version as Source (either gratis + or for a Distributor Fee, and with or without a Compiled form of the + Modified Version) provided that you clearly document how it differs + from the Standard Version, including, but not limited to, documenting + any non-standard features, executables, or modules, and provided that + you do at least ONE of the following: + . + (a) make the Modified Version available to the Copyright Holder + of the Standard Version, under the Original License, so that the + Copyright Holder may include your modifications in the Standard + Version. + . + (b) ensure that installation of your Modified Version does not + prevent the user installing or running the Standard Version. In + addition, the Modified Version must bear a name that is different + from the name of the Standard Version. + . + (c) allow anyone who receives a copy of the Modified Version to + make the Source form of the Modified Version available to others + under + . + (i) the Original License or + . + (ii) a license that permits the licensee to freely copy, + modify and redistribute the Modified Version using the same + licensing terms that apply to the copy that the licensee + received, and requires that the Source form of the Modified + Version, and of any works derived from it, be made freely + available in that license fees are prohibited but Distributor + Fees are allowed. + . + Distribution of Compiled Forms of the Standard Version + or Modified Versions without the Source + . + (5) You may Distribute Compiled forms of the Standard Version without + the Source, provided that you include complete instructions on how to + get the Source of the Standard Version. Such instructions must be + valid at the time of your distribution. If these instructions, at any + time while you are carrying out such distribution, become invalid, you + must provide new instructions on demand or cease further distribution. + If you provide valid instructions or cease distribution within thirty + days after you become aware that the instructions are invalid, then + you do not forfeit any of your rights under this license. + . + (6) You may Distribute a Modified Version in Compiled form without + the Source, provided that you comply with Section 4 with respect to + the Source of the Modified Version. + . + Aggregating or Linking the Package + . + (7) You may aggregate the Package (either the Standard Version or + Modified Version) with other packages and Distribute the resulting + aggregation provided that you do not charge a licensing fee for the + Package. Distributor Fees are permitted, and licensing fees for other + components in the aggregation are permitted. The terms of this license + apply to the use and Distribution of the Standard or Modified Versions + as included in the aggregation. + . + (8) You are permitted to link Modified and Standard Versions with + other works, to embed the Package in a larger work of your own, or to + build stand-alone binary or bytecode versions of applications that + include the Package, and Distribute the result without restriction, + provided the result does not expose a direct interface to the Package. + . + Items That are Not Considered Part of a Modified Version + . + (9) Works (including, but not limited to, modules and scripts) that + merely extend or make use of the Package, do not, by themselves, cause + the Package to be a Modified Version. In addition, such works are not + considered parts of the Package itself, and are not subject to the + terms of this license. + . + General Provisions + . + (10) Any use, modification, and distribution of the Standard or + Modified Versions is governed by this Artistic License. By using, + modifying or distributing the Package, you accept this license. Do not + use, modify, or distribute the Package, if you do not accept this + license. + . + (11) If your Modified Version has been derived from a Modified + Version made by someone other than you, you are nevertheless required + to ensure that your Modified Version complies with the requirements of + this license. + . + (12) This license does not grant you the right to use any trademark, + service mark, tradename, or logo of the Copyright Holder. + . + (13) This license includes the non-exclusive, worldwide, + free-of-charge patent license to make, have made, use, offer to sell, + sell, import and otherwise transfer the Package with respect to any + patent claims licensable by the Copyright Holder that are necessarily + infringed by the Package. If you institute patent litigation + (including a cross-claim or counterclaim) against any party alleging + that the Package constitutes direct or contributory patent + infringement, then this Artistic License to you shall terminate on the + date that such litigation is filed. + . + (14) Disclaimer of Warranty: + THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS + IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR + NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL + LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL + DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +License: BSD-2-clause + All rights reserved. + . + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + . + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + . + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + . + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +License: Bormann-Degener + Any use of this software is permitted provided that this notice is not + removed and that neither the authors nor the Technische Universitaet Berlin + are deemed to have made any representations as to the suitability of this + software for any purpose nor are held responsible for any defects of + this software. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + . + As a matter of courtesy, the authors request to be informed about uses + this software has found, about bugs in this software, and about any + improvements that may be of general interest. + +License: CC-BY-SA-3 + Creative Commons Legal Code + . + Attribution-ShareAlike 3.0 Unported + . + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR + DAMAGES RESULTING FROM ITS USE. + . + License + . + THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE + COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY + COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS + AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. + . + BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE + TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY + BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS + CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND + CONDITIONS. + . + 1. Definitions + . + a. "Adaptation" means a work based upon the Work, or upon the Work and + other pre-existing works, such as a translation, adaptation, + derivative work, arrangement of music or other alterations of a + literary or artistic work, or phonogram or performance and includes + cinematographic adaptations or any other form in which the Work may be + recast, transformed, or adapted including in any form recognizably + derived from the original, except that a work that constitutes a + Collection will not be considered an Adaptation for the purpose of + this License. For the avoidance of doubt, where the Work is a musical + work, performance or phonogram, the synchronization of the Work in + timed-relation with a moving image ("synching") will be considered an + Adaptation for the purpose of this License. + b. "Collection" means a collection of literary or artistic works, such as + encyclopedias and anthologies, or performances, phonograms or + broadcasts, or other works or subject matter other than works listed + in Section 1(f) below, which, by reason of the selection and + arrangement of their contents, constitute intellectual creations, in + which the Work is included in its entirety in unmodified form along + with one or more other contributions, each constituting separate and + independent works in themselves, which together are assembled into a + collective whole. A work that constitutes a Collection will not be + considered an Adaptation (as defined below) for the purposes of this + License. + c. "Creative Commons Compatible License" means a license that is listed + at https://creativecommons.org/compatiblelicenses that has been + approved by Creative Commons as being essentially equivalent to this + License, including, at a minimum, because that license: (i) contains + terms that have the same purpose, meaning and effect as the License + Elements of this License; and, (ii) explicitly permits the relicensing + of adaptations of works made available under that license under this + License or a Creative Commons jurisdiction license with the same + License Elements as this License. + d. "Distribute" means to make available to the public the original and + copies of the Work or Adaptation, as appropriate, through sale or + other transfer of ownership. + e. "License Elements" means the following high-level license attributes + as selected by Licensor and indicated in the title of this License: + Attribution, ShareAlike. + f. "Licensor" means the individual, individuals, entity or entities that + offer(s) the Work under the terms of this License. + g. "Original Author" means, in the case of a literary or artistic work, + the individual, individuals, entity or entities who created the Work + or if no individual or entity can be identified, the publisher; and in + addition (i) in the case of a performance the actors, singers, + musicians, dancers, and other persons who act, sing, deliver, declaim, + play in, interpret or otherwise perform literary or artistic works or + expressions of folklore; (ii) in the case of a phonogram the producer + being the person or legal entity who first fixes the sounds of a + performance or other sounds; and, (iii) in the case of broadcasts, the + organization that transmits the broadcast. + h. "Work" means the literary and/or artistic work offered under the terms + of this License including without limitation any production in the + literary, scientific and artistic domain, whatever may be the mode or + form of its expression including digital form, such as a book, + pamphlet and other writing; a lecture, address, sermon or other work + of the same nature; a dramatic or dramatico-musical work; a + choreographic work or entertainment in dumb show; a musical + composition with or without words; a cinematographic work to which are + assimilated works expressed by a process analogous to cinematography; + a work of drawing, painting, architecture, sculpture, engraving or + lithography; a photographic work to which are assimilated works + expressed by a process analogous to photography; a work of applied + art; an illustration, map, plan, sketch or three-dimensional work + relative to geography, topography, architecture or science; a + performance; a broadcast; a phonogram; a compilation of data to the + extent it is protected as a copyrightable work; or a work performed by + a variety or circus performer to the extent it is not otherwise + considered a literary or artistic work. + i. "You" means an individual or entity exercising rights under this + License who has not previously violated the terms of this License with + respect to the Work, or who has received express permission from the + Licensor to exercise rights under this License despite a previous + violation. + j. "Publicly Perform" means to perform public recitations of the Work and + to communicate to the public those public recitations, by any means or + process, including by wire or wireless means or public digital + performances; to make available to the public Works in such a way that + members of the public may access these Works from a place and at a + place individually chosen by them; to perform the Work to the public + by any means or process and the communication to the public of the + performances of the Work, including by public digital performance; to + broadcast and rebroadcast the Work by any means including signs, + sounds or images. + k. "Reproduce" means to make copies of the Work by any means including + without limitation by sound or visual recordings and the right of + fixation and reproducing fixations of the Work, including storage of a + protected performance or phonogram in digital form or other electronic + medium. + . + 2. Fair Dealing Rights. Nothing in this License is intended to reduce, + limit, or restrict any uses free from copyright or rights arising from + limitations or exceptions that are provided for in connection with the + copyright protection under copyright law or other applicable laws. + . + 3. License Grant. Subject to the terms and conditions of this License, + Licensor hereby grants You a worldwide, royalty-free, non-exclusive, + perpetual (for the duration of the applicable copyright) license to + exercise the rights in the Work as stated below: + . + a. to Reproduce the Work, to incorporate the Work into one or more + Collections, and to Reproduce the Work as incorporated in the + Collections; + b. to create and Reproduce Adaptations provided that any such Adaptation, + including any translation in any medium, takes reasonable steps to + clearly label, demarcate or otherwise identify that changes were made + to the original Work. For example, a translation could be marked "The + original work was translated from English to Spanish," or a + modification could indicate "The original work has been modified."; + c. to Distribute and Publicly Perform the Work including as incorporated + in Collections; and, + d. to Distribute and Publicly Perform Adaptations. + e. For the avoidance of doubt: + . + i. Non-waivable Compulsory License Schemes. In those jurisdictions in + which the right to collect royalties through any statutory or + compulsory licensing scheme cannot be waived, the Licensor + reserves the exclusive right to collect such royalties for any + exercise by You of the rights granted under this License; + ii. Waivable Compulsory License Schemes. In those jurisdictions in + which the right to collect royalties through any statutory or + compulsory licensing scheme can be waived, the Licensor waives the + exclusive right to collect such royalties for any exercise by You + of the rights granted under this License; and, + iii. Voluntary License Schemes. The Licensor waives the right to + collect royalties, whether individually or, in the event that the + Licensor is a member of a collecting society that administers + voluntary licensing schemes, via that society, from any exercise + by You of the rights granted under this License. + . + The above rights may be exercised in all media and formats whether now + known or hereafter devised. The above rights include the right to make + such modifications as are technically necessary to exercise the rights in + other media and formats. Subject to Section 8(f), all rights not expressly + granted by Licensor are hereby reserved. + . + 4. Restrictions. The license granted in Section 3 above is expressly made + subject to and limited by the following restrictions: + . + a. You may Distribute or Publicly Perform the Work only under the terms + of this License. You must include a copy of, or the Uniform Resource + Identifier (URI) for, this License with every copy of the Work You + Distribute or Publicly Perform. You may not offer or impose any terms + on the Work that restrict the terms of this License or the ability of + the recipient of the Work to exercise the rights granted to that + recipient under the terms of the License. You may not sublicense the + Work. You must keep intact all notices that refer to this License and + to the disclaimer of warranties with every copy of the Work You + Distribute or Publicly Perform. When You Distribute or Publicly + Perform the Work, You may not impose any effective technological + measures on the Work that restrict the ability of a recipient of the + Work from You to exercise the rights granted to that recipient under + the terms of the License. This Section 4(a) applies to the Work as + incorporated in a Collection, but this does not require the Collection + apart from the Work itself to be made subject to the terms of this + License. If You create a Collection, upon notice from any Licensor You + must, to the extent practicable, remove from the Collection any credit + as required by Section 4(c), as requested. If You create an + Adaptation, upon notice from any Licensor You must, to the extent + practicable, remove from the Adaptation any credit as required by + Section 4(c), as requested. + b. You may Distribute or Publicly Perform an Adaptation only under the + terms of: (i) this License; (ii) a later version of this License with + the same License Elements as this License; (iii) a Creative Commons + jurisdiction license (either this or a later license version) that + contains the same License Elements as this License (e.g., + Attribution-ShareAlike 3.0 US)); (iv) a Creative Commons Compatible + License. If you license the Adaptation under one of the licenses + mentioned in (iv), you must comply with the terms of that license. If + you license the Adaptation under the terms of any of the licenses + mentioned in (i), (ii) or (iii) (the "Applicable License"), you must + comply with the terms of the Applicable License generally and the + following provisions: (I) You must include a copy of, or the URI for, + the Applicable License with every copy of each Adaptation You + Distribute or Publicly Perform; (II) You may not offer or impose any + terms on the Adaptation that restrict the terms of the Applicable + License or the ability of the recipient of the Adaptation to exercise + the rights granted to that recipient under the terms of the Applicable + License; (III) You must keep intact all notices that refer to the + Applicable License and to the disclaimer of warranties with every copy + of the Work as included in the Adaptation You Distribute or Publicly + Perform; (IV) when You Distribute or Publicly Perform the Adaptation, + You may not impose any effective technological measures on the + Adaptation that restrict the ability of a recipient of the Adaptation + from You to exercise the rights granted to that recipient under the + terms of the Applicable License. This Section 4(b) applies to the + Adaptation as incorporated in a Collection, but this does not require + the Collection apart from the Adaptation itself to be made subject to + the terms of the Applicable License. + c. If You Distribute, or Publicly Perform the Work or any Adaptations or + Collections, You must, unless a request has been made pursuant to + Section 4(a), keep intact all copyright notices for the Work and + provide, reasonable to the medium or means You are utilizing: (i) the + name of the Original Author (or pseudonym, if applicable) if supplied, + and/or if the Original Author and/or Licensor designate another party + or parties (e.g., a sponsor institute, publishing entity, journal) for + attribution ("Attribution Parties") in Licensor's copyright notice, + terms of service or by other reasonable means, the name of such party + or parties; (ii) the title of the Work if supplied; (iii) to the + extent reasonably practicable, the URI, if any, that Licensor + specifies to be associated with the Work, unless such URI does not + refer to the copyright notice or licensing information for the Work; + and (iv) , consistent with Ssection 3(b), in the case of an + Adaptation, a credit identifying the use of the Work in the Adaptation + (e.g., "French translation of the Work by Original Author," or + "Screenplay based on original Work by Original Author"). The credit + required by this Section 4(c) may be implemented in any reasonable + manner; provided, however, that in the case of a Adaptation or + Collection, at a minimum such credit will appear, if a credit for all + contributing authors of the Adaptation or Collection appears, then as + part of these credits and in a manner at least as prominent as the + credits for the other contributing authors. For the avoidance of + doubt, You may only use the credit required by this Section for the + purpose of attribution in the manner set out above and, by exercising + Your rights under this License, You may not implicitly or explicitly + assert or imply any connection with, sponsorship or endorsement by the + Original Author, Licensor and/or Attribution Parties, as appropriate, + of You or Your use of the Work, without the separate, express prior + written permission of the Original Author, Licensor and/or Attribution + Parties. + d. Except as otherwise agreed in writing by the Licensor or as may be + otherwise permitted by applicable law, if You Reproduce, Distribute or + Publicly Perform the Work either by itself or as part of any + Adaptations or Collections, You must not distort, mutilate, modify or + take other derogatory action in relation to the Work which would be + prejudicial to the Original Author's honor or reputation. Licensor + agrees that in those jurisdictions (e.g. Japan), in which any exercise + of the right granted in Section 3(b) of this License (the right to + make Adaptations) would be deemed to be a distortion, mutilation, + modification or other derogatory action prejudicial to the Original + Author's honor and reputation, the Licensor will waive or not assert, + as appropriate, this Section, to the fullest extent permitted by the + applicable national law, to enable You to reasonably exercise Your + right under Section 3(b) of this License (right to make Adaptations) + but not otherwise. + . + 5. Representations, Warranties and Disclaimer + . + UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR + OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY + KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, + INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, + FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF + LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, + WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION + OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU. + . + 6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE + LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR + ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES + ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS + BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + . + 7. Termination + . + a. This License and the rights granted hereunder will terminate + automatically upon any breach by You of the terms of this License. + Individuals or entities who have received Adaptations or Collections + from You under this License, however, will not have their licenses + terminated provided such individuals or entities remain in full + compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will + survive any termination of this License. + b. Subject to the above terms and conditions, the license granted here is + perpetual (for the duration of the applicable copyright in the Work). + Notwithstanding the above, Licensor reserves the right to release the + Work under different license terms or to stop distributing the Work at + any time; provided, however that any such election will not serve to + withdraw this License (or any other license that has been, or is + required to be, granted under the terms of this License), and this + License will continue in full force and effect unless terminated as + stated above. + . + 8. Miscellaneous + . + a. Each time You Distribute or Publicly Perform the Work or a Collection, + the Licensor offers to the recipient a license to the Work on the same + terms and conditions as the license granted to You under this License. + b. Each time You Distribute or Publicly Perform an Adaptation, Licensor + offers to the recipient a license to the original Work on the same + terms and conditions as the license granted to You under this License. + c. If any provision of this License is invalid or unenforceable under + applicable law, it shall not affect the validity or enforceability of + the remainder of the terms of this License, and without further action + by the parties to this agreement, such provision shall be reformed to + the minimum extent necessary to make such provision valid and + enforceable. + d. No term or provision of this License shall be deemed waived and no + breach consented to unless such waiver or consent shall be in writing + and signed by the party to be charged with such waiver or consent. + e. This License constitutes the entire agreement between the parties with + respect to the Work licensed here. There are no understandings, + agreements or representations with respect to the Work not specified + here. Licensor shall not be bound by any additional provisions that + may appear in any communication from You. This License may not be + modified without the mutual written agreement of the Licensor and You. + f. The rights granted under, and the subject matter referenced, in this + License were drafted utilizing the terminology of the Berne Convention + for the Protection of Literary and Artistic Works (as amended on + September 28, 1979), the Rome Convention of 1961, the WIPO Copyright + Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996 + and the Universal Copyright Convention (as revised on July 24, 1971). + These rights and subject matter take effect in the relevant + jurisdiction in which the License terms are sought to be enforced + according to the corresponding provisions of the implementation of + those treaty provisions in the applicable national law. If the + standard suite of rights granted under applicable copyright law + includes additional rights not granted under this License, such + additional rights are deemed to be included in the License; this + License is not intended to restrict the license of any rights under + applicable law. + . + Creative Commons Notice + . + Creative Commons is not a party to this License, and makes no warranty + whatsoever in connection with the Work. Creative Commons will not be + liable to You or any party on any legal theory for any damages + whatsoever, including without limitation any general, special, + incidental or consequential damages arising in connection to this + license. Notwithstanding the foregoing two (2) sentences, if Creative + Commons has expressly identified itself as the Licensor hereunder, it + shall have all rights and obligations of Licensor. + . + Except for the limited purpose of indicating to the public that the + Work is licensed under the CCPL, Creative Commons does not authorize + the use by either party of the trademark "Creative Commons" or any + related trademark or logo of Creative Commons without the prior + written consent of Creative Commons. Any permitted use will be in + compliance with Creative Commons' then-current trademark usage + guidelines, as may be published on its website or otherwise made + available upon request from time to time. For the avoidance of doubt, + this trademark restriction does not form part of the License. + . + Creative Commons may be contacted at https://creativecommons.org/. + +License: CC-BY-SA-4 + Attribution-ShareAlike 4.0 International + . + ======================================================================= + . + Creative Commons Corporation ("Creative Commons") is not a law firm and + does not provide legal services or legal advice. Distribution of + Creative Commons public licenses does not create a lawyer-client or + other relationship. Creative Commons makes its licenses and related + information available on an "as-is" basis. Creative Commons gives no + warranties regarding its licenses, any material licensed under their + terms and conditions, or any related information. Creative Commons + disclaims all liability for damages resulting from their use to the + fullest extent possible. + . + Using Creative Commons Public Licenses + . + Creative Commons public licenses provide a standard set of terms and + conditions that creators and other rights holders may use to share + original works of authorship and other material subject to copyright + and certain other rights specified in the public license below. The + following considerations are for informational purposes only, are not + exhaustive, and do not form part of our licenses. + . + Considerations for licensors: Our public licenses are + intended for use by those authorized to give the public + permission to use material in ways otherwise restricted by + copyright and certain other rights. Our licenses are + irrevocable. Licensors should read and understand the terms + and conditions of the license they choose before applying it. + Licensors should also secure all rights necessary before + applying our licenses so that the public can reuse the + material as expected. Licensors should clearly mark any + material not subject to the license. This includes other CC- + licensed material, or material used under an exception or + limitation to copyright. More considerations for licensors: + wiki.creativecommons.org/Considerations_for_licensors + . + Considerations for the public: By using one of our public + licenses, a licensor grants the public permission to use the + licensed material under specified terms and conditions. If + the licensor's permission is not necessary for any reason--for + example, because of any applicable exception or limitation to + copyright--then that use is not regulated by the license. Our + licenses grant only permissions under copyright and certain + other rights that a licensor has authority to grant. Use of + the licensed material may still be restricted for other + reasons, including because others have copyright or other + rights in the material. A licensor may make special requests, + such as asking that all changes be marked or described. + Although not required by our licenses, you are encouraged to + respect those requests where reasonable. More considerations + for the public: + wiki.creativecommons.org/Considerations_for_licensees + . + ======================================================================= + . + Creative Commons Attribution-ShareAlike 4.0 International Public + License + . + By exercising the Licensed Rights (defined below), You accept and agree + to be bound by the terms and conditions of this Creative Commons + Attribution-ShareAlike 4.0 International Public License ("Public + License"). To the extent this Public License may be interpreted as a + contract, You are granted the Licensed Rights in consideration of Your + acceptance of these terms and conditions, and the Licensor grants You + such rights in consideration of benefits the Licensor receives from + making the Licensed Material available under these terms and + conditions. + . + . + Section 1 -- Definitions. + . + a. Adapted Material means material subject to Copyright and Similar + Rights that is derived from or based upon the Licensed Material + and in which the Licensed Material is translated, altered, + arranged, transformed, or otherwise modified in a manner requiring + permission under the Copyright and Similar Rights held by the + Licensor. For purposes of this Public License, where the Licensed + Material is a musical work, performance, or sound recording, + Adapted Material is always produced where the Licensed Material is + synched in timed relation with a moving image. + . + b. Adapter's License means the license You apply to Your Copyright + and Similar Rights in Your contributions to Adapted Material in + accordance with the terms and conditions of this Public License. + . + c. BY-SA Compatible License means a license listed at + creativecommons.org/compatiblelicenses, approved by Creative + Commons as essentially the equivalent of this Public License. + . + d. Copyright and Similar Rights means copyright and/or similar rights + closely related to copyright including, without limitation, + performance, broadcast, sound recording, and Sui Generis Database + Rights, without regard to how the rights are labeled or + categorized. For purposes of this Public License, the rights + specified in Section 2(b)(1)-(2) are not Copyright and Similar + Rights. + . + e. Effective Technological Measures means those measures that, in the + absence of proper authority, may not be circumvented under laws + fulfilling obligations under Article 11 of the WIPO Copyright + Treaty adopted on December 20, 1996, and/or similar international + agreements. + . + f. Exceptions and Limitations means fair use, fair dealing, and/or + any other exception or limitation to Copyright and Similar Rights + that applies to Your use of the Licensed Material. + . + g. License Elements means the license attributes listed in the name + of a Creative Commons Public License. The License Elements of this + Public License are Attribution and ShareAlike. + . + h. Licensed Material means the artistic or literary work, database, + or other material to which the Licensor applied this Public + License. + . + i. Licensed Rights means the rights granted to You subject to the + terms and conditions of this Public License, which are limited to + all Copyright and Similar Rights that apply to Your use of the + Licensed Material and that the Licensor has authority to license. + . + j. Licensor means the individual(s) or entity(ies) granting rights + under this Public License. + . + k. Share means to provide material to the public by any means or + process that requires permission under the Licensed Rights, such + as reproduction, public display, public performance, distribution, + dissemination, communication, or importation, and to make material + available to the public including in ways that members of the + public may access the material from a place and at a time + individually chosen by them. + . + l. Sui Generis Database Rights means rights other than copyright + resulting from Directive 96/9/EC of the European Parliament and of + the Council of 11 March 1996 on the legal protection of databases, + as amended and/or succeeded, as well as other essentially + equivalent rights anywhere in the world. + . + m. You means the individual or entity exercising the Licensed Rights + under this Public License. Your has a corresponding meaning. + . + . + Section 2 -- Scope. + . + a. License grant. + . + 1. Subject to the terms and conditions of this Public License, + the Licensor hereby grants You a worldwide, royalty-free, + non-sublicensable, non-exclusive, irrevocable license to + exercise the Licensed Rights in the Licensed Material to: + . + a. reproduce and Share the Licensed Material, in whole or + in part; and + . + b. produce, reproduce, and Share Adapted Material. + . + 2. Exceptions and Limitations. For the avoidance of doubt, where + Exceptions and Limitations apply to Your use, this Public + License does not apply, and You do not need to comply with + its terms and conditions. + . + 3. Term. The term of this Public License is specified in Section + 6(a). + . + 4. Media and formats; technical modifications allowed. The + Licensor authorizes You to exercise the Licensed Rights in + all media and formats whether now known or hereafter created, + and to make technical modifications necessary to do so. The + Licensor waives and/or agrees not to assert any right or + authority to forbid You from making technical modifications + necessary to exercise the Licensed Rights, including + technical modifications necessary to circumvent Effective + Technological Measures. For purposes of this Public License, + simply making modifications authorized by this Section 2(a) + (4) never produces Adapted Material. + . + 5. Downstream recipients. + . + a. Offer from the Licensor -- Licensed Material. Every + recipient of the Licensed Material automatically + receives an offer from the Licensor to exercise the + Licensed Rights under the terms and conditions of this + Public License. + . + b. Additional offer from the Licensor -- Adapted Material. + Every recipient of Adapted Material from You + automatically receives an offer from the Licensor to + exercise the Licensed Rights in the Adapted Material + under the conditions of the Adapter's License You apply. + . + c. No downstream restrictions. You may not offer or impose + any additional or different terms or conditions on, or + apply any Effective Technological Measures to, the + Licensed Material if doing so restricts exercise of the + Licensed Rights by any recipient of the Licensed + Material. + . + 6. No endorsement. Nothing in this Public License constitutes or + may be construed as permission to assert or imply that You + are, or that Your use of the Licensed Material is, connected + with, or sponsored, endorsed, or granted official status by, + the Licensor or others designated to receive attribution as + provided in Section 3(a)(1)(A)(i). + . + b. Other rights. + . + 1. Moral rights, such as the right of integrity, are not + licensed under this Public License, nor are publicity, + privacy, and/or other similar personality rights; however, to + the extent possible, the Licensor waives and/or agrees not to + assert any such rights held by the Licensor to the limited + extent necessary to allow You to exercise the Licensed + Rights, but not otherwise. + . + 2. Patent and trademark rights are not licensed under this + Public License. + . + 3. To the extent possible, the Licensor waives any right to + collect royalties from You for the exercise of the Licensed + Rights, whether directly or through a collecting society + under any voluntary or waivable statutory or compulsory + licensing scheme. In all other cases the Licensor expressly + reserves any right to collect such royalties. + . + . + Section 3 -- License Conditions. + . + Your exercise of the Licensed Rights is expressly made subject to the + following conditions. + . + a. Attribution. + . + 1. If You Share the Licensed Material (including in modified + form), You must: + . + a. retain the following if it is supplied by the Licensor + with the Licensed Material: + . + i. identification of the creator(s) of the Licensed + Material and any others designated to receive + attribution, in any reasonable manner requested by + the Licensor (including by pseudonym if + designated); + . + ii. a copyright notice; + . + iii. a notice that refers to this Public License; + . + iv. a notice that refers to the disclaimer of + warranties; + . + v. a URI or hyperlink to the Licensed Material to the + extent reasonably practicable; + . + b. indicate if You modified the Licensed Material and + retain an indication of any previous modifications; and + . + c. indicate the Licensed Material is licensed under this + Public License, and include the text of, or the URI or + hyperlink to, this Public License. + . + 2. You may satisfy the conditions in Section 3(a)(1) in any + reasonable manner based on the medium, means, and context in + which You Share the Licensed Material. For example, it may be + reasonable to satisfy the conditions by providing a URI or + hyperlink to a resource that includes the required + information. + . + 3. If requested by the Licensor, You must remove any of the + information required by Section 3(a)(1)(A) to the extent + reasonably practicable. + . + b. ShareAlike. + . + In addition to the conditions in Section 3(a), if You Share + Adapted Material You produce, the following conditions also apply. + . + 1. The Adapter's License You apply must be a Creative Commons + license with the same License Elements, this version or + later, or a BY-SA Compatible License. + . + 2. You must include the text of, or the URI or hyperlink to, the + Adapter's License You apply. You may satisfy this condition + in any reasonable manner based on the medium, means, and + context in which You Share Adapted Material. + . + 3. You may not offer or impose any additional or different terms + or conditions on, or apply any Effective Technological + Measures to, Adapted Material that restrict exercise of the + rights granted under the Adapter's License You apply. + . + . + Section 4 -- Sui Generis Database Rights. + . + Where the Licensed Rights include Sui Generis Database Rights that + apply to Your use of the Licensed Material: + . + a. for the avoidance of doubt, Section 2(a)(1) grants You the right + to extract, reuse, reproduce, and Share all or a substantial + portion of the contents of the database; + . + b. if You include all or a substantial portion of the database + contents in a database in which You have Sui Generis Database + Rights, then the database in which You have Sui Generis Database + Rights (but not its individual contents) is Adapted Material, + . + including for purposes of Section 3(b); and + c. You must comply with the conditions in Section 3(a) if You Share + all or a substantial portion of the contents of the database. + . + For the avoidance of doubt, this Section 4 supplements and does not + replace Your obligations under this Public License where the Licensed + Rights include other Copyright and Similar Rights. + . + . + Section 5 -- Disclaimer of Warranties and Limitation of Liability. + . + a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE + EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS + AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF + ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, + IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, + WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, + ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT + KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT + ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. + . + b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE + TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, + NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, + INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, + COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR + USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR + DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR + IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. + . + c. The disclaimer of warranties and limitation of liability provided + above shall be interpreted in a manner that, to the extent + possible, most closely approximates an absolute disclaimer and + waiver of all liability. + . + . + Section 6 -- Term and Termination. + . + a. This Public License applies for the term of the Copyright and + Similar Rights licensed here. However, if You fail to comply with + this Public License, then Your rights under this Public License + terminate automatically. + . + b. Where Your right to use the Licensed Material has terminated under + Section 6(a), it reinstates: + . + 1. automatically as of the date the violation is cured, provided + it is cured within 30 days of Your discovery of the + violation; or + . + 2. upon express reinstatement by the Licensor. + . + For the avoidance of doubt, this Section 6(b) does not affect any + right the Licensor may have to seek remedies for Your violations + of this Public License. + . + c. For the avoidance of doubt, the Licensor may also offer the + Licensed Material under separate terms or conditions or stop + distributing the Licensed Material at any time; however, doing so + will not terminate this Public License. + . + d. Sections 1, 5, 6, 7, and 8 survive termination of this Public + License. + . + . + Section 7 -- Other Terms and Conditions. + . + a. The Licensor shall not be bound by any additional or different + terms or conditions communicated by You unless expressly agreed. + . + b. Any arrangements, understandings, or agreements regarding the + Licensed Material not stated herein are separate from and + independent of the terms and conditions of this Public License. + . + . + Section 8 -- Interpretation. + . + a. For the avoidance of doubt, this Public License does not, and + shall not be interpreted to, reduce, limit, restrict, or impose + conditions on any use of the Licensed Material that could lawfully + be made without permission under this Public License. + . + b. To the extent possible, if any provision of this Public License is + deemed unenforceable, it shall be automatically reformed to the + minimum extent necessary to make it enforceable. If the provision + cannot be reformed, it shall be severed from this Public License + without affecting the enforceability of the remaining terms and + conditions. + . + c. No term or condition of this Public License will be waived and no + failure to comply consented to unless expressly agreed to by the + Licensor. + . + d. Nothing in this Public License constitutes or may be interpreted + as a limitation upon, or waiver of, any privileges and immunities + that apply to the Licensor or You, including from the legal + processes of any jurisdiction or authority. + . + . + ======================================================================= + . + Creative Commons is not a party to its public + licenses. Notwithstanding, Creative Commons may elect to apply one of + its public licenses to material it publishes and in those instances + will be considered the “Licensor.” The text of the Creative Commons + public licenses is dedicated to the public domain under the CC0 Public + Domain Dedication. Except for the limited purpose of indicating that + material is shared under a Creative Commons public license or as + otherwise permitted by the Creative Commons policies published at + creativecommons.org/policies, Creative Commons does not authorize the + use of the trademark "Creative Commons" or any other trademark or logo + of Creative Commons without its prior written consent including, + without limitation, in connection with any unauthorized modifications + to any of its public licenses or any other arrangements, + understandings, or agreements concerning use of licensed material. For + the avoidance of doubt, this paragraph does not form part of the + public licenses. + . + Creative Commons may be contacted at creativecommons.org. + +License: Expat + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + . + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + . + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +License: GPL-2+ + 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; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + . + On Debian systems, the complete text of the GNU General Public License + can be found in `/usr/share/common-licenses/GPL-2'. + +License: LGPL-2+ + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + . + This library 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 + Library General Public License for more details. + . + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + . + On Debian systems, the complete text of the GNU Library General Public License + can be found in `/usr/share/common-licenses/LGPL-2'. + +License: LGPL-2.1+ + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + . + This library 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 + Lesser General Public License for more details. + . + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + . + On Debian systems, the complete text of the GNU Lesser General Public License + can be found in `/usr/share/common-licenses/LGPL-2.1'. + +License: WOL + Permission to use, copy, modify, distribute and sell this software and its + 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 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/gbp.conf b/debian/gbp.conf new file mode 100644 index 000000000..cec628c74 --- /dev/null +++ b/debian/gbp.conf @@ -0,0 +1,2 @@ +[DEFAULT] +pristine-tar = True diff --git a/debian/lmms-bin.install b/debian/lmms-bin.install new file mode 100644 index 000000000..229fa02e3 --- /dev/null +++ b/debian/lmms-bin.install @@ -0,0 +1,4 @@ +usr/bin/lmms +usr/lib/*/lmms/ladspa/* +usr/lib/*/lmms/lib* +usr/lib/*/lmms/RemoteZynAddSubFx diff --git a/debian/lmms-bin.lintian-overrides b/debian/lmms-bin.lintian-overrides new file mode 100644 index 000000000..45e07c39d --- /dev/null +++ b/debian/lmms-bin.lintian-overrides @@ -0,0 +1,9 @@ +lmms: pkg-has-shlibs-control-file-but-no-actual-shared-libs +lmms: postinst-has-useless-call-to-ldconfig +lmms: postrm-has-useless-call-to-ldconfig + +# env is used to set the environment, then lmms is called. +lmms: desktop-command-not-in-package usr/share/applications/lmms.desktop env + +# Icon is in lmms-common. +lmms: menu-icon-missing usr/share/pixmaps/lmms.xpm diff --git a/debian/lmms-common.docs b/debian/lmms-common.docs new file mode 100644 index 000000000..a7b624a0a --- /dev/null +++ b/debian/lmms-common.docs @@ -0,0 +1 @@ +plugins/LadspaEffect/caps/caps.html diff --git a/debian/lmms-common.install b/debian/lmms-common.install new file mode 100644 index 000000000..467ee8798 --- /dev/null +++ b/debian/lmms-common.install @@ -0,0 +1,25 @@ +usr/share/applications +usr/share/bash-completion +usr/share/icons +usr/share/lmms/[a-o]* +usr/share/lmms/presets/[A-Y]* +usr/share/lmms/projects/demos/Alf42red-* +usr/share/lmms/projects/demos/CapDan +usr/share/lmms/projects/demos/EsoXLB-* +usr/share/lmms/projects/demos/Impulslogik-* +usr/share/lmms/projects/demos/Jousboxx-* +usr/share/lmms/projects/demos/Momo64-* +usr/share/lmms/projects/demos/Oglsdl-* +usr/share/lmms/projects/demos/Settel-* +usr/share/lmms/projects/demos/Socceroos-* +usr/share/lmms/projects/demos/TameAnderson-* +usr/share/lmms/projects/demos/Thomasso-* +usr/share/lmms/projects/shorties/Crunk* +usr/share/lmms/projects/shorties/Greshz-* +usr/share/lmms/projects/shorties/Surrender-* +usr/share/lmms/projects/templates +usr/share/lmms/projects/tutorials +usr/share/lmms/[q-z]* +usr/share/man +usr/share/mime +debian/lmms.xpm usr/share/pixmaps/ diff --git a/debian/lmms-common.links b/debian/lmms-common.links new file mode 100644 index 000000000..75596233c --- /dev/null +++ b/debian/lmms-common.links @@ -0,0 +1 @@ +usr/share/zynaddsubfx/banks usr/share/lmms/presets/ZynAddSubFX diff --git a/debian/lmms-common.maintscript b/debian/lmms-common.maintscript new file mode 100644 index 000000000..15d673556 --- /dev/null +++ b/debian/lmms-common.maintscript @@ -0,0 +1 @@ +dir_to_symlink /usr/share/lmms/presets/ZynAddSubFX ../../zynaddsubfx/banks 1.1.3-2~ diff --git a/debian/lmms-vst-server.install b/debian/lmms-vst-server.install new file mode 100644 index 000000000..60efaed7b --- /dev/null +++ b/debian/lmms-vst-server.install @@ -0,0 +1 @@ +usr/lib/*/lmms/{32/,}RemoteVstPlugin* diff --git a/debian/lmms.xpm b/debian/lmms.xpm new file mode 100644 index 000000000..425e3156d --- /dev/null +++ b/debian/lmms.xpm @@ -0,0 +1,103 @@ +/* XPM */ +static char * lmms_xpm[] = { +"24 24 76 1", +" c None", +". c #208B4D", +"+ c #208C4D", +"@ c #229452", +"# c #239654", +"$ c #239754", +"% c #299557", +"& c #2A9658", +"* c #239B56", +"= c #249B56", +"- c #249C57", +"; c #249D57", +"> c #259E58", +", c #259F59", +"' c #25A059", +") c #25A15A", +"! c #25A25A", +"~ c #25A35A", +"{ c #26A35B", +"] c #26A45B", +"^ c #26A55C", +"/ c #26A65C", +"( c #26A65D", +"_ c #3E9E67", +": c #26A75D", +"< c #28A75E", +"[ c #28A75F", +"} c #27A85E", +"| c #27A95E", +"1 c #27AA5F", +"2 c #27AB5F", +"3 c #29AC60", +"4 c #2AAC61", +"5 c #2FAC64", +"6 c #54A275", +"7 c #33AE67", +"8 c #56A477", +"9 c #2AB365", +"0 c #5BA67B", +"a c #3CB36F", +"b c #41B572", +"c c #64B285", +"d c #50BA7D", +"e c #58B881", +"f c #5CBA84", +"g c #56BC82", +"h c #5FBB86", +"i c #34D07B", +"j c #34D17A", +"k c #34D17B", +"l c #68C28F", +"m c #77C899", +"n c #7DCD9F", +"o c #90C7A8", +"p c #8CD2AA", +"q c #9AD7B4", +"r c #A9DDBF", +"s c #B0E0C5", +"t c #BDDDCB", +"u c #C3DFCF", +"v c #BFE6CF", +"w c #CBE3D5", +"x c #C5E6D3", +"y c #CDE9D9", +"z c #D1EDDD", +"A c #D7EFE2", +"B c #E1F0E8", +"C c #E6F5EC", +"D c #EAF6EF", +"E c #F3FAF6", +"F c #F7FBF9", +"G c #F8FBFA", +"H c #F6FCF9", +"I c #FCFEFD", +"J c #FDFEFE", +"K c #FFFFFF", +" ", +" kiiiiiiiiiiiiiiiiiij ", +" j92222222222222222229i ", +" i22222222222222222222i ", +" i22222222asvb22222222i ", +" i2222223nEKKHp4222222i ", +" i11111dzKKKKKKAg11111i ", +" i|||5qIKKBccBKKJr7|||i ", +" i}}lCKKFo%))&oGKKDm}}i ", +" i::KKKt_*(::(*_tKKK::i ", +" i//KKK@~//////~@KKK//i ", +" i^^KKK^^^^^^^^^^KKK^^i ", +" i]]KKK]]]]]]]]]]KKK]]i ", +" i{{KKKf{{{{{{{{fKKK{{i ", +" i!!KKKKyh!!!!exKKKK!!i ", +" i))KKKKKK))))KKKKKK))i ", +" i''KKKKKK''''KKKKKK''i ", +" i,,KKKKKK,,,,KKKKKK,,i ", +" i>>6uKKw0>>>>6uKKw0>>i ", +" i;;$+88.$;;;;$+88.$;;i ", +" i----##--------##----i ", +" j<==================[i ", +" jiiiiiiiiiiiiiiiiiii ", +" "}; diff --git a/debian/patches/build-amd64-20181013.patch b/debian/patches/build-amd64-20181013.patch new file mode 100644 index 000000000..9f8182903 --- /dev/null +++ b/debian/patches/build-amd64-20181013.patch @@ -0,0 +1,46 @@ +Description: Fix build as of 2018-10-13 + Fix build errors, possibly introduced with GCC 8. +Author: Javier Serrano Polo +Bug-Debian: https://bugs.debian.org/897806 + +Index: lmms-1.1.3/plugins/LadspaEffect/caps/dsp/FPTruncateMode.h +=================================================================== +--- lmms-1.1.3.orig/plugins/LadspaEffect/caps/dsp/FPTruncateMode.h ++++ lmms-1.1.3/plugins/LadspaEffect/caps/dsp/FPTruncateMode.h +@@ -40,9 +40,11 @@ class FPTruncateMode + + FPTruncateMode() + { ++#ifdef __i386__ + fstcw (cw0); + cw1 = cw0 | 0xC00; + fldcw (cw1); ++#endif + } + + ~FPTruncateMode() +Index: lmms-1.1.3/plugins/zynaddsubfx/zynaddsubfx/src/Synth/OscilGen.cpp +=================================================================== +--- lmms-1.1.3.orig/plugins/zynaddsubfx/zynaddsubfx/src/Synth/OscilGen.cpp ++++ lmms-1.1.3/plugins/zynaddsubfx/zynaddsubfx/src/Synth/OscilGen.cpp +@@ -33,7 +33,8 @@ + //operations on FFTfreqs + inline void clearAll(fft_t *freqs) + { +- memset(freqs, 0, synth->oscilsize / 2 * sizeof(fft_t)); ++ for(int i = 0; i < synth->oscilsize / 2; ++i) ++ freqs[i] = fft_t(0.0f, 0.0f); + } + + inline void clearDC(fft_t *freqs) +@@ -928,8 +929,8 @@ void OscilGen::getspectrum(int n, float + if(what == 0) { + for(int i = 0; i < n; ++i) + outoscilFFTfreqs[i] = fft_t(spc[i], spc[i]); +- memset(outoscilFFTfreqs + n, 0, +- (synth->oscilsize / 2 - n) * sizeof(fft_t)); ++ for(int i = n; i < synth->oscilsize / 2; ++i) ++ outoscilFFTfreqs[i] = fft_t(0.0f, 0.0f); + adaptiveharmonic(outoscilFFTfreqs, 0.0f); + adaptiveharmonicpostprocess(outoscilFFTfreqs, n - 1); + for(int i = 0; i < n; ++i) diff --git a/debian/patches/clang.patch b/debian/patches/clang.patch new file mode 100644 index 000000000..2e2a0a2f1 --- /dev/null +++ b/debian/patches/clang.patch @@ -0,0 +1,601 @@ +Description: Fix build with Clang + Several issues are present: + - Unused private elements. + - Wrong use of delete. + - Unsupported compiler options. + - Shifting negative values. + - Possible truncations. + - Uninitialized variables. + - Unused code. + - Hiding overloaded virtual functions. + - Declarations outside namespace. + - Mismatched class tag. + . + Be careful editing this patch because allegrosmfwr.cpp has CRLF terminators. +Author: Javier Serrano Polo +Bug: https://github.com/LMMS/lmms/issues/3073 + +Index: lmms-1.1.3/include/AutomatableModel.h +=================================================================== +--- lmms-1.1.3.orig/include/AutomatableModel.h 2017-01-03 13:01:47.000000000 +0100 ++++ lmms-1.1.3/include/AutomatableModel.h 2017-01-03 13:11:25.000000000 +0100 +@@ -307,7 +307,6 @@ + + // most objects will need this temporarily (until sampleExact is + // standard) +- float m_oldValue; + int m_setValueDepth; + + AutoModelVector m_linkedModels; +Index: lmms-1.1.3/plugins/LadspaEffect/calf/CMakeLists.txt +=================================================================== +--- lmms-1.1.3.orig/plugins/LadspaEffect/calf/CMakeLists.txt 2017-01-03 16:03:14.000000000 +0100 ++++ lmms-1.1.3/plugins/LadspaEffect/calf/CMakeLists.txt 2017-01-03 16:14:28.000000000 +0100 +@@ -7,11 +7,22 @@ + "${CMAKE_CURRENT_SOURCE_DIR}/src") + INSTALL(TARGETS calf LIBRARY DESTINATION "${PLUGIN_DIR}/ladspa") + SET_TARGET_PROPERTIES(calf PROPERTIES PREFIX "") ++ + SET(INLINE_FLAGS "") +-IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") +-SET(INLINE_FLAGS "-finline-functions-called-once -finline-limit=80") ++ ++INCLUDE(CheckCXXCompilerFlag) ++CHECK_CXX_COMPILER_FLAG(-finline-functions CXX_HAVE_INLINE_FUNCTIONS) ++IF(${CXX_HAVE_INLINE_FUNCTIONS}) ++ SET(INLINE_FLAGS "${INLINE_FLAGS} -finline-functions") + ENDIF() +-SET_TARGET_PROPERTIES(calf PROPERTIES COMPILE_FLAGS "-O2 -finline-functions ${INLINE_FLAGS}") ++CHECK_CXX_COMPILER_FLAG(-finline-functions-called-once ++ CXX_HAVE_INLINE_FUNCTIONS_CALLED_ONCE) ++IF(${CXX_HAVE_INLINE_FUNCTIONS_CALLED_ONCE}) ++ SET(INLINE_FLAGS "${INLINE_FLAGS} -finline-functions-called-once \ ++ -finline-limit=80") ++ENDIF() ++ ++SET_TARGET_PROPERTIES(calf PROPERTIES COMPILE_FLAGS "-O2 ${INLINE_FLAGS}") + + IF(LMMS_BUILD_WIN32) + ADD_CUSTOM_COMMAND(TARGET calf POST_BUILD COMMAND "${STRIP}" "\"${CMAKE_CURRENT_BINARY_DIR}/calf.dll\"") +Index: lmms-1.1.3/plugins/LadspaEffect/calf/src/calf/metadata.h +=================================================================== +--- lmms-1.1.3.orig/plugins/LadspaEffect/calf/src/calf/metadata.h 2017-01-03 17:41:17.000000000 +0100 ++++ lmms-1.1.3/plugins/LadspaEffect/calf/src/calf/metadata.h 2017-01-03 17:50:40.000000000 +0100 +@@ -51,7 +51,7 @@ + enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, rt_capable = true, require_midi = false, support_midi = false }; + PLUGIN_NAME_ID_LABEL("filter", "filter", "Filter") + /// do not export mode and inertia as CVs, as those are settings and not parameters +- bool is_cv(int param_no) { return param_no != par_mode && param_no != par_inertia; } ++ bool is_cv(int param_no) const { return param_no != par_mode && param_no != par_inertia; } + }; + + /// Filterclavier - metadata +@@ -61,7 +61,7 @@ + enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, rt_capable = true, require_midi = true, support_midi = true }; + PLUGIN_NAME_ID_LABEL("filterclavier", "filterclavier", "Filterclavier") + /// do not export mode and inertia as CVs, as those are settings and not parameters +- bool is_cv(int param_no) { return param_no != par_mode && param_no != par_inertia; } ++ bool is_cv(int param_no) const { return param_no != par_mode && param_no != par_inertia; } + }; + + struct reverb_metadata: public plugin_metadata +@@ -499,7 +499,7 @@ + PLUGIN_NAME_ID_LABEL("organ", "organ", "Organ") + + public: +- plugin_command_info *get_commands(); ++ plugin_command_info *get_commands() const; + const char *const *get_configure_vars() const; + }; + +Index: lmms-1.1.3/plugins/LadspaEffect/calf/src/calf/modules.h +=================================================================== +--- lmms-1.1.3.orig/plugins/LadspaEffect/calf/src/calf/modules.h 2017-01-03 19:02:59.000000000 +0100 ++++ lmms-1.1.3/plugins/LadspaEffect/calf/src/calf/modules.h 2017-01-03 19:30:35.000000000 +0100 +@@ -89,13 +89,14 @@ + using audio_module::ins; + using audio_module::outs; + using audio_module::params; ++ using FilterClass::calculate_filter; + + dsp::inertia inertia_cutoff, inertia_resonance, inertia_gain; + dsp::once_per_n timer; + bool is_active; + mutable volatile int last_generation, last_calculated_generation; + +- filter_module_with_inertia(float **ins, float **outs, float **params) ++ filter_module_with_inertia() + : inertia_cutoff(dsp::exponential_ramp(128), 20) + , inertia_resonance(dsp::exponential_ramp(128), 20) + , inertia_gain(dsp::exponential_ramp(128), 1.0) +@@ -193,7 +194,7 @@ + mutable float old_cutoff, old_resonance, old_mode; + public: + filter_audio_module() +- : filter_module_with_inertia(ins, outs, params) ++ : filter_module_with_inertia() + { + last_generation = 0; + old_mode = old_resonance = old_cutoff = -1; +Index: lmms-1.1.3/plugins/LadspaEffect/calf/src/calf/modules_comp.h +=================================================================== +--- lmms-1.1.3.orig/plugins/LadspaEffect/calf/src/calf/modules_comp.h 2017-01-03 19:35:53.000000000 +0100 ++++ lmms-1.1.3/plugins/LadspaEffect/calf/src/calf/modules_comp.h 2017-01-03 19:38:06.000000000 +0100 +@@ -39,10 +39,10 @@ + class gain_reduction_audio_module + { + private: +- float linSlope, detected, kneeSqrt, kneeStart, linKneeStart, kneeStop; ++ float linSlope, detected, kneeStart, linKneeStart, kneeStop; + float compressedKneeStop, adjKneeStart, thres; + float attack, release, threshold, ratio, knee, makeup, detection, stereo_link, bypass, mute, meter_out, meter_comp; +- mutable float old_threshold, old_ratio, old_knee, old_makeup, old_bypass, old_mute, old_detection, old_stereo_link; ++ mutable float old_threshold, old_ratio, old_knee, old_makeup, old_bypass, old_mute, old_detection; + mutable volatile int last_generation; + uint32_t srate; + bool is_active; +@@ -69,7 +69,7 @@ + /// Main gate routine by Damien called by various audio modules + class expander_audio_module { + private: +- float linSlope, peak, detected, kneeSqrt, kneeStart, linKneeStart, kneeStop, linKneeStop; ++ float linSlope, detected, kneeStart, linKneeStart, kneeStop, linKneeStop; + float compressedKneeStop, adjKneeStart, range, thres, attack_coeff, release_coeff; + float attack, release, threshold, ratio, knee, makeup, detection, stereo_link, bypass, mute, meter_out, meter_gate; + mutable float old_threshold, old_ratio, old_knee, old_makeup, old_bypass, old_range, old_trigger, old_mute, old_detection, old_stereo_link; +@@ -142,7 +142,7 @@ + mutable float f1_freq_old, f2_freq_old, f1_level_old, f2_level_old; + mutable float f1_freq_old1, f2_freq_old1, f1_level_old1, f2_level_old1; + CalfScModes sc_mode; +- mutable CalfScModes sc_mode_old, sc_mode_old1; ++ mutable CalfScModes sc_mode_old1; + float f1_active, f2_active; + stereo_in_out_metering meters; + gain_reduction_audio_module compressor; +Index: lmms-1.1.3/plugins/LadspaEffect/calf/src/calf/modules_limit.h +=================================================================== +--- lmms-1.1.3.orig/plugins/LadspaEffect/calf/src/calf/modules_limit.h 2017-01-03 19:39:00.000000000 +0100 ++++ lmms-1.1.3/plugins/LadspaEffect/calf/src/calf/modules_limit.h 2017-01-03 19:40:20.000000000 +0100 +@@ -37,7 +37,6 @@ + private: + typedef limiter_audio_module AM; + uint32_t clip_inL, clip_inR, clip_outL, clip_outR, asc_led; +- int mode, mode_old; + float meter_inL, meter_inR, meter_outL, meter_outR; + dsp::lookahead_limiter limiter; + public: +@@ -73,7 +72,6 @@ + unsigned int overall_buffer_size; + float *buffer; + int channels; +- float striprel[strips]; + float weight[strips]; + float weight_old[strips]; + float limit_old; +Index: lmms-1.1.3/plugins/LadspaEffect/calf/src/calf/modules_mod.h +=================================================================== +--- lmms-1.1.3.orig/plugins/LadspaEffect/calf/src/calf/modules_mod.h 2017-01-03 19:41:55.000000000 +0100 ++++ lmms-1.1.3/plugins/LadspaEffect/calf/src/calf/modules_mod.h 2017-01-03 19:42:19.000000000 +0100 +@@ -160,8 +160,6 @@ + typedef pulsator_audio_module AM; + uint32_t clip_inL, clip_inR, clip_outL, clip_outR; + float meter_inL, meter_inR, meter_outL, meter_outR; +- float offset_old; +- int mode_old; + bool clear_reset; + dsp::simple_lfo lfoL, lfoR; + public: +Index: lmms-1.1.3/plugins/LadspaEffect/calf/src/calf/organ.h +=================================================================== +--- lmms-1.1.3.orig/plugins/LadspaEffect/calf/src/calf/organ.h 2017-01-03 19:43:08.000000000 +0100 ++++ lmms-1.1.3/plugins/LadspaEffect/calf/src/calf/organ.h 2017-01-03 19:53:55.000000000 +0100 +@@ -318,6 +318,7 @@ + using drawbar_organ::note_on; + using drawbar_organ::note_off; + using drawbar_organ::control_change; ++ using drawbar_organ::pitch_bend; + enum { param_count = drawbar_organ::param_count}; + dsp::organ_parameters par_values; + uint32_t srate; +@@ -338,9 +339,9 @@ + void deactivate(); + uint32_t process(uint32_t offset, uint32_t nsamples, uint32_t inputs_mask, uint32_t outputs_mask); + /// No CV inputs for now +- bool is_cv(int param_no) { return false; } ++ bool is_cv(int param_no) const { return false; } + /// Practically all the stuff here is noisy +- bool is_noisy(int param_no) { return true; } ++ bool is_noisy(int param_no) const { return true; } + void execute(int cmd_no); + bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const; + char *configure(const char *key, const char *value); +Index: lmms-1.1.3/plugins/LadspaEffect/calf/src/calf/preset.h +=================================================================== +--- lmms-1.1.3.orig/plugins/LadspaEffect/calf/src/calf/preset.h 2017-01-03 19:57:02.000000000 +0100 ++++ lmms-1.1.3/plugins/LadspaEffect/calf/src/calf/preset.h 2017-01-03 20:00:25.000000000 +0100 +@@ -27,7 +27,7 @@ + + namespace calf_plugins { + +-class plugin_ctl_iface; ++struct plugin_ctl_iface; + + /// Contents of single preset + struct plugin_preset +Index: lmms-1.1.3/plugins/LadspaEffect/calf/src/calf/primitives.h +=================================================================== +--- lmms-1.1.3.orig/plugins/LadspaEffect/calf/src/calf/primitives.h 2017-01-03 17:36:12.000000000 +0100 ++++ lmms-1.1.3/plugins/LadspaEffect/calf/src/calf/primitives.h 2017-01-03 16:22:16.000000000 +0100 +@@ -370,11 +370,6 @@ + next_task = (unsigned)-1; + eob = false; + } +- inline bool is_next_tick() { +- if (time < next_task) +- return true; +- do_tasks(); +- } + inline void next_tick() { + time++; + } +@@ -382,14 +377,6 @@ + timeline.insert(std::pair(time+pos, t)); + next_task = timeline.begin()->first; + } +- void do_tasks() { +- std::multimap::iterator i = timeline.begin(); +- while(i != timeline.end() && i->first == time) { +- i->second->execute(this); +- i->second->dispose(); +- timeline.erase(i); +- } +- } + bool is_eob() { + return eob; + } +Index: lmms-1.1.3/plugins/LadspaEffect/calf/src/metadata.cpp +=================================================================== +--- lmms-1.1.3.orig/plugins/LadspaEffect/calf/src/metadata.cpp 2017-01-03 17:52:03.000000000 +0100 ++++ lmms-1.1.3/plugins/LadspaEffect/calf/src/metadata.cpp 2017-01-03 18:49:18.000000000 +0100 +@@ -29,6 +29,8 @@ + + const char *calf_plugins::calf_copyright_info = "(C) 2001-2009 Krzysztof Foltman, Thor Harald Johanssen, Markus Schmidt and others; license: LGPL"; + ++namespace calf_plugins { ++ + //////////////////////////////////////////////////////////////////////////// + + CALF_PORT_NAMES(flanger) = {"In L", "In R", "Out L", "Out R"}; +@@ -1105,7 +1107,7 @@ + + CALF_PLUGIN_INFO(organ) = { 0x8481, "Organ", "Calf Organ", "Krzysztof Foltman", calf_plugins::calf_copyright_info, "SynthesizerPlugin" }; + +-plugin_command_info *organ_metadata::get_commands() ++plugin_command_info *organ_metadata::get_commands() const + { + static plugin_command_info cmds[] = { + { "cmd_panic", "Panic!", "Stop all sounds and reset all controllers" }, +@@ -1439,6 +1441,8 @@ + + //////////////////////////////////////////////////////////////////////////// + ++}; // namespace calf_plugins ++ + calf_plugins::plugin_registry::plugin_registry() + { + #define PER_MODULE_ITEM(name, isSynth, jackname) plugins.push_back((new name##_metadata)); +Index: lmms-1.1.3/plugins/LadspaEffect/calf/src/modules.cpp +=================================================================== +--- lmms-1.1.3.orig/plugins/LadspaEffect/calf/src/modules.cpp 2017-01-03 19:32:38.000000000 +0100 ++++ lmms-1.1.3/plugins/LadspaEffect/calf/src/modules.cpp 2017-01-03 19:33:13.000000000 +0100 +@@ -339,7 +339,7 @@ + /////////////////////////////////////////////////////////////////////////////////////////////// + + filterclavier_audio_module::filterclavier_audio_module() +-: filter_module_with_inertia(ins, outs, params) ++: filter_module_with_inertia() + , min_gain(1.0) + , max_gain(32.0) + , last_note(-1) +Index: lmms-1.1.3/plugins/LadspaEffect/swh/flanger_1191.c +=================================================================== +--- lmms-1.1.3.orig/plugins/LadspaEffect/swh/flanger_1191.c 2017-01-03 15:44:13.000000000 +0100 ++++ lmms-1.1.3/plugins/LadspaEffect/swh/flanger_1191.c 2017-01-03 15:45:17.000000000 +0100 +@@ -266,7 +266,7 @@ + + // Calculate position in delay table + d_base = LIN_INTERP(frac, old_d_base, new_d_base); +- n_ph = (float)(law_p - abs(next_law_pos - count))/(float)law_p; ++ n_ph = (float)(law_p - labs(next_law_pos - count))/(float)law_p; + p_ph = n_ph + 0.5f; + while (p_ph > 1.0f) { + p_ph -= 1.0f; +@@ -392,7 +392,7 @@ + + // Calculate position in delay table + d_base = LIN_INTERP(frac, old_d_base, new_d_base); +- n_ph = (float)(law_p - abs(next_law_pos - count))/(float)law_p; ++ n_ph = (float)(law_p - labs(next_law_pos - count))/(float)law_p; + p_ph = n_ph + 0.5f; + while (p_ph > 1.0f) { + p_ph -= 1.0f; +Index: lmms-1.1.3/plugins/LadspaEffect/swh/gsm/short_term.c +=================================================================== +--- lmms-1.1.3.orig/plugins/LadspaEffect/swh/gsm/short_term.c 2017-01-03 15:35:13.000000000 +0100 ++++ lmms-1.1.3/plugins/LadspaEffect/swh/gsm/short_term.c 2017-01-03 15:35:55.000000000 +0100 +@@ -53,7 +53,7 @@ + #undef STEP + #define STEP( B, MIC, INVA ) \ + temp1 = GSM_ADD( *LARc++, MIC ) << 10; \ +- temp1 = GSM_SUB( temp1, B << 1 ); \ ++ temp1 = GSM_SUB( temp1, B * 2 ); \ + temp1 = GSM_MULT_R( INVA, temp1 ); \ + *LARpp++ = GSM_ADD( temp1, temp1 ); + +Index: lmms-1.1.3/plugins/LadspaEffect/swh/multivoice_chorus_1201.c +=================================================================== +--- lmms-1.1.3.orig/plugins/LadspaEffect/swh/multivoice_chorus_1201.c 2017-01-03 15:47:51.000000000 +0100 ++++ lmms-1.1.3/plugins/LadspaEffect/swh/multivoice_chorus_1201.c 2017-01-03 15:48:18.000000000 +0100 +@@ -345,7 +345,7 @@ + if (count % 16 < laws) { + unsigned int t = count % 16; + // Calculate sinus phases +- float n_ph = (float)(law_p - abs(next_peak_pos[t] - count))/law_p; ++ float n_ph = (float)(law_p - labs(next_peak_pos[t] - count))/law_p; + float p_ph = n_ph + 0.5f; + if (p_ph > 1.0f) { + p_ph -= 1.0f; +@@ -488,7 +488,7 @@ + if (count % 16 < laws) { + unsigned int t = count % 16; + // Calculate sinus phases +- float n_ph = (float)(law_p - abs(next_peak_pos[t] - count))/law_p; ++ float n_ph = (float)(law_p - labs(next_peak_pos[t] - count))/law_p; + float p_ph = n_ph + 0.5f; + if (p_ph > 1.0f) { + p_ph -= 1.0f; +Index: lmms-1.1.3/plugins/LadspaEffect/swh/retro_flange_1208.c +=================================================================== +--- lmms-1.1.3.orig/plugins/LadspaEffect/swh/retro_flange_1208.c 2017-01-03 15:46:35.000000000 +0100 ++++ lmms-1.1.3/plugins/LadspaEffect/swh/retro_flange_1208.c 2017-01-03 15:47:02.000000000 +0100 +@@ -321,7 +321,7 @@ + prev_law_pos = count + law_p; + } + +- n_ph = (float)(law_p - abs(next_law_pos - count))/(float)law_p; ++ n_ph = (float)(law_p - labs(next_law_pos - count))/(float)law_p; + p_ph = n_ph + 0.5f; + if (p_ph > 1.0f) { + p_ph -= 1.0f; +@@ -446,7 +446,7 @@ + prev_law_pos = count + law_p; + } + +- n_ph = (float)(law_p - abs(next_law_pos - count))/(float)law_p; ++ n_ph = (float)(law_p - labs(next_law_pos - count))/(float)law_p; + p_ph = n_ph + 0.5f; + if (p_ph > 1.0f) { + p_ph -= 1.0f; +Index: lmms-1.1.3/plugins/LadspaEffect/swh/vynil_1905.c +=================================================================== +--- lmms-1.1.3.orig/plugins/LadspaEffect/swh/vynil_1905.c 2017-01-03 15:51:56.000000000 +0100 ++++ lmms-1.1.3/plugins/LadspaEffect/swh/vynil_1905.c 2017-01-03 16:01:32.000000000 +0100 +@@ -243,6 +243,8 @@ + buffer_s = malloc(sizeof(LADSPA_Data) * buffer_size); + buffer_mask = buffer_size - 1; + buffer_pos = 0; ++ click_buffer_omega.all = 0; ++ click_buffer_pos.all = 0; + click_gain = 0; + phi = 0.0f; /* Angular phase */ + +Index: lmms-1.1.3/plugins/LadspaEffect/tap/CMakeLists.txt +=================================================================== +--- lmms-1.1.3.orig/plugins/LadspaEffect/tap/CMakeLists.txt 2017-01-03 13:52:28.000000000 +0100 ++++ lmms-1.1.3/plugins/LadspaEffect/tap/CMakeLists.txt 2017-01-03 15:12:14.000000000 +0100 +@@ -1,7 +1,15 @@ + INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/include") + FILE(GLOB PLUGIN_SOURCES *.c) + LIST(SORT PLUGIN_SOURCES) +-SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3 -Wno-write-strings -fomit-frame-pointer -fno-strict-aliasing -fstrength-reduce -funroll-loops -ffast-math") ++SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3 -Wno-write-strings \ ++ -fomit-frame-pointer -fno-strict-aliasing -funroll-loops -ffast-math") ++ ++INCLUDE(CheckCCompilerFlag) ++CHECK_C_COMPILER_FLAG(-fstrength-reduce C_HAVE_STRENGTH_REDUCE) ++IF(${C_HAVE_STRENGTH_REDUCE}) ++ SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstrength-reduce") ++ENDIF() ++ + FOREACH(_item ${PLUGIN_SOURCES}) + GET_FILENAME_COMPONENT(_plugin "${_item}" NAME_WE) + ADD_LIBRARY("${_plugin}" MODULE "${_item}") +Index: lmms-1.1.3/plugins/MidiImport/portsmf/allegro.h +=================================================================== +--- lmms-1.1.3.orig/plugins/MidiImport/portsmf/allegro.h 2017-01-03 20:02:37.000000000 +0100 ++++ lmms-1.1.3/plugins/MidiImport/portsmf/allegro.h 2017-01-03 20:06:48.000000000 +0100 +@@ -842,6 +842,8 @@ + Alg_event_ptr write_track_name(std::ostream &file, int n, + Alg_events &events); + public: ++ using Alg_track::paste; ++ + int channel_offset_per_track; // used to encode track_num into channel + Alg_tracks track_list; // array of Alg_events + Alg_time_sigs time_sig; +Index: lmms-1.1.3/plugins/MidiImport/portsmf/allegrosmfwr.cpp +=================================================================== +--- lmms-1.1.3.orig/plugins/MidiImport/portsmf/allegrosmfwr.cpp 2017-01-03 20:07:50.000000000 +0100 ++++ lmms-1.1.3/plugins/MidiImport/portsmf/allegrosmfwr.cpp 2017-01-03 20:08:34.000000000 +0100 +@@ -57,13 +57,11 @@ + + Alg_seq_ptr seq; + +- int num_tracks; // number of tracks not counting tempo track + int division; // divisions per quarter note, default = 120 + int initial_tempo; + + int timesig_num; // numerator of time signature + int timesig_den; // denominator of time signature +- double timesig_when; // time of time signature + + int keysig; // number of sharps (+) or flats (-), -99 for undefined + char keysig_mode; // 'M' or 'm' for major/minor +Index: lmms-1.1.3/plugins/delay/stereodelay.cpp +=================================================================== +--- lmms-1.1.3.orig/plugins/delay/stereodelay.cpp 2017-01-03 13:40:27.000000000 +0100 ++++ lmms-1.1.3/plugins/delay/stereodelay.cpp 2017-01-03 13:42:16.000000000 +0100 +@@ -48,7 +48,7 @@ + { + if( m_buffer ) + { +- delete m_buffer; ++ delete[] m_buffer; + } + } + +@@ -84,7 +84,7 @@ + { + if( m_buffer ) + { +- delete m_buffer; ++ delete[] m_buffer; + } + + int bufferSize = ( int )( sampleRate * m_maxTime ); +Index: lmms-1.1.3/plugins/opl2/fmopl.c +=================================================================== +--- lmms-1.1.3.orig/plugins/opl2/fmopl.c 2017-01-03 20:11:03.000000000 +0100 ++++ lmms-1.1.3/plugins/opl2/fmopl.c 2017-01-03 20:22:23.000000000 +0100 +@@ -70,7 +70,7 @@ + /* final output shift , limit minimum and maximum */ + #define OPL_OUTSB (TL_BITS+3-16) /* OPL output final shift 16bit */ + #define OPL_MAXOUT (0x7fff< + Developer Rubén Ibarra Pastor diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 7aca74d87..859c5f2c6 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -15,3 +15,6 @@ if(DOXYGEN_FOUND) COMMENT "Generating API documentation with Doxygen" SOURCES Doxyfile.in) endif(DOXYGEN_FOUND) + +ADD_SUBDIRECTORY(bash-completion) + diff --git a/doc/CONTRIBUTORS b/doc/CONTRIBUTORS new file mode 100644 index 000000000..4a791028f --- /dev/null +++ b/doc/CONTRIBUTORS @@ -0,0 +1,185 @@ +Tobias Junghans +Vesa +Tres Finocchiaro +Lukas W +Javier Serrano Polo +Paul Giblock +Dave French +Colin Wallace +Oskar Wallgren +Raine M. Ekman +Umcaruje +Michael Gregorius +Javier Serrano Polo +grejppi +Javier Serrano Polo +Hyunjin Song +Wong Cho Ching +Alexandre Almeida +Daniel Winzen +LMMS Service Account +Steffen Baranowsky +Danny McRae +Garrett +Hyunin Song +liushuyu +Andrew Kelley +Andreas Brandmaier +Fastigium +Spekular +Amadeus Folego +Jonas Trappenberg +M374LX +DomClark +grindhold +Mike Choi +Karmo Rosental +Christopher L. Simons +Dominic Clark +NoiseByNorthwest +falkTX +Johannes Lorenz +Rebecca DeField +Stian Jørgensrud +Ryan Roden-Corrent +midi-pascal +Augustin Cavalier +BaraMGB +Csaba Hruska +David Carlier +DeRobyJ +Hussam Eddin Alhomsi +Rüdiger Ranft +StakeoutPunch +ma2moto +mikobuntu +8tab <8tab@wp.pl> +Andrés +Matthew Krafczyk +mohamed +Alexandre +RebeccaDeField +Yann Collette +Aya Morisawa +Ben Bryan +Jonathan Aquilina +Mohammad Amin Sameti +ra +wongcc966422 +David CARLIER +Gurjot Singh +Janne Sinisalo +Krzysztof Foltman +Lou Herard +Paul Batchelor +Paul Wayper +Petter Reinholdtsen +TonyChyi +dnl-music +follower +midi-pascal +unfa +Andres +Arnout Engelen +Chris Aiken +Cyrille Bollu +Dan Williams +Ian Sannar +Jaroslav Petrnoušek +Johannes Lorenz <1042576+JohannesLorenz@users.noreply.github.com> +Johannes Lorenz +Kenneth Perry (thothonegan) +LYF610400210 +Lukas W +Mark-Agent003 +NeiroNext +Orbital Ink <31394502+Anonymouqs@users.noreply.github.com> +P THE AWESOME +Ra +Rafael Ruggiero +Rebecca LaVie +Roberto Giaconia +SecondFlight +Steffen Baranowsky +TheTravelingSpaceman +Thomas Clark +gnudles +liushuyu +miketurn +psyomn +quadro +sarahkeefe +Achim Settelmeier +André Hentschel +Armin Kazmi +Attila Herman +Bastian Kummer +Christopher A. Oliver +Devin Venable +Diego Ramos Ruggeri +Douglas <34612565+DouglasDGI@users.noreply.github.com> +DragonEagle +Filip Hron +Frank Mather +Frederik +Greg Simpson +Hexasoft +IvanMaldonado +Ivo Wetzel +Jens Lang +Jesse Dubay +Joel Muzzerall +Joshua Wade +Jousboxx +Jérôme Duval +Karmo Rosental +Kristi +Lee Avital +LocoMatt +Léo Andrès +Markus Elfring +Maurizio Lo Bosco +Mehdi +Mikobuntu +Mingcong Bai +Nikos Chantziaras +Noah Brecht +Ododo +Olivier Humbert +Paul Nasca +Peter Nelson +Ra +Ryan Schmidt +Shane Ambler +Simon Jackson (Netbook) +Simon van der Veldt +Stephen Seo +Steve Leonard +The Gitter Badger +Thorsten Müller +Tobias Junghans +Tobias Kortkamp +Tyler Ganter +Uroš Šišović +Wiley Yu +anonymous +devin +fholmer +flynn16 +follower +fundamental +gandalf3 +groboclown +irrenhaus3 +jasp00 +justnope +kamnxt +lmmsservice +m-xbutterfly +noahb01 +projectpitchin +rgwan +xhe +xy124 +z-up +zm1990s diff --git a/doc/bash-completion/CMakeLists.txt b/doc/bash-completion/CMakeLists.txt new file mode 100644 index 000000000..783e13a71 --- /dev/null +++ b/doc/bash-completion/CMakeLists.txt @@ -0,0 +1,4 @@ +INCLUDE(BashCompletion) +IF(COMMAND BASHCOMP_INSTALL) + BASHCOMP_INSTALL(lmms) +ENDIF() diff --git a/doc/bash-completion/lmms b/doc/bash-completion/lmms new file mode 100644 index 000000000..ccff8f249 --- /dev/null +++ b/doc/bash-completion/lmms @@ -0,0 +1,335 @@ +#!/usr/bin/env bash +# lmms(1) completion -*- shell-script -*- +# use shellcheck: "shellcheck -e bash " + +_lmms_array_contains () +{ + local e match="$1" + shift + for e; do [[ "$e" == "$match" ]] && return 0; done + return 1 +} + +_lmms_long_param_of() +{ + case "$1" in + -a) + echo "float" + ;; + -b) + echo "bitrate" + ;; + -c) + echo "config" + ;; + -f) + echo "format" + ;; + -i) + echo "interpolation" + ;; + -l) + echo "loop" + ;; + -m) + echo "mode" + ;; + -o) + echo "output" + ;; + -p) + echo "profile" + ;; + -s) + echo "samplerate" + ;; + -x) + echo "oversampling" + ;; + *) + echo "" + ;; + esac +} + +_lmms_conv_old_action () +{ + case "$1" in + -d|--dump) + echo "dump" + ;; + -r|--render) + echo "render" + ;; + --rendertracks) + echo "rendertracks" + ;; + -u|--upgrade) + echo "upgrade" + ;; + *) + echo "" + ;; + esac +} + +_lmms() +{ + local cword=$COMP_CWORD + local cur="${COMP_WORDS[COMP_CWORD]}" + + # call routine provided by bash-completion + _init_completion || return + + local params filemode filetypes + local i # counter variable + local pars_global pars_noaction pars_render actions shortargs + pars_global=(--allowroot --config --help --version) + pars_noaction=(--geometry --import) + pars_render=(--float --bitrate --format --interpolation) + pars_render+=(--loop --mode --output --profile) + pars_render+=(--samplerate --oversampling) + actions=(dump render rendertracks upgrade) + actions_old=(-d --dump -r --render --rendertracks -u --upgrade) + shortargs+=(-a -b -c -f -h -i -l -m -o -p -s -v -x) + + local prev prev2 + if [ "$cword" -gt 1 ] + then + prev=${COMP_WORDS[cword-1]} + fi + if [ "$cword" -gt 2 ] + then + prev2=${COMP_WORDS[cword-2]} + fi + + # don't show shortargs, but complete them when entered + if [[ $cur =~ ^-[^-]$ ]] + then + if _lmms_array_contains "$cur" "${shortargs[@]}" + then + COMPREPLY=( "$cur" ) + fi + return + fi + + # + # please keep those in order like def_pars_args above + # + case $prev in + --bitrate|-b) + params="64 96 128 160 192 256 320" + ;; + --config|-c) + filetypes='xml' + filemode='existing_files' + ;; + --format|-f) + params='wav ogg mp3' + ;; + --geometry) + # we can not name all possibilities, but this helps the user + # by showing them how the format is + params='0x0+0+0' + ;; + --interpolation|-i) + params='linear sincfastest sincmedium sincbest' + ;; + --import) + filetypes='mid|midi|MID|MIDI|rmi|RMI|h2song|H2SONG' + filemode='existing_files' + ;; + --mode|-m) + params='s j m' + ;; + --output|-o) + # default assumption: could be both + local render=1 rendertracks=1 + for i in "${!COMP_WORDS[@]}" + do + if [[ ${COMP_WORDS[i]} =~ ^(render|-r|--render)$ ]] + then + rendertracks= + elif [[ ${COMP_WORDS[i]} =~ ^(rendertracks|--rendertracks)$ ]] + then + render= + fi + done + if [ "$rendertracks" ] + then + filemode='existing_directories' + fi + if [ "$render" ] + then + # filemode files is a superset of "existing directories" + # so it's OK to overwrite the filemode='existing_directories' + # from above + filetypes='wav|ogg|mp3' + filemode='files' + fi + ;; + --profile|-p) + filemode='files' + ;; + --samplerate|-s) + # these are the ones suggested for zyn + # if you think more are required, + # remove this comment and write a justification + params='44100 48000 96000 192000' + ;; + --oversampling|-x) + params='1 2 4 8' + ;; + *) + local action_found + + # Is an action specified? + if [ "$cword" -gt 1 ] + then + local wrd + for wrd in "${COMP_WORDS[@]}" + do + # action named explicitly? + if _lmms_array_contains "$wrd" "${actions[@]}" + then + action_found=$wrd + break + # deprecated action name? + elif _lmms_array_contains "$wrd" "${actions_old[@]}" + then + action_found="$(_lmms_conv_old_action "$wrd")" + break + # no-action params found? + elif _lmms_array_contains "$wrd" "${pars_noaction[@]}" + then + action_found=none + break + fi + done + fi + + if [[ $prev =~ -e|--help|-h|-version|-v ]] + then + # the -e flag (from --import) and help/version + # always mark the end of arguments + return + fi + + if [[ "$action_found" =~ dump|none|^$ ]] && [[ $prev =~ \.mmpz? ]] + then + # mmp(z) mark the end of arguments for those actions + return + fi + + local savefiletypes='mmpz|mmp' + local params_array + + # find parameters/filetypes/dirtypes depending on actions + if ! [ "$action_found" ] + then + params_array=( "${actions[@]}" "${pars_global[@]}" "${pars_noaction[@]}") + filemode="existing_files" + filetypes="$savefiletypes" + elif [ "$action_found" == "none" ] + then + params_array=( "${pars_noaction[@]}" ) + filemode="existing_files" + filetypes="$savefiletypes" + elif [ "$action_found" == "dump" ] + then + filemode="existing_files" + filetypes="mmpz" + elif [ "$action_found" == "upgrade" ] + then + if [ "$prev" == "upgrade" ] + then + filemode="existing_files" + filetypes="$savefiletypes" + elif [ "$prev2" == "upgrade" ] + then + filemode="files" + filetypes="$savefiletypes" + fi + elif [[ "$action_found" =~ render(tracks)? ]] + then + if [[ "$prev" =~ render(tracks)? ]] + then + filemode="existing_files" + filetypes="$savefiletypes" + else + params_array=( "${pars_render[@]}" ) + fi + fi + + # add params_array to params, but also check the history of comp words + local param + for param in "${params_array[@]}" + do + local do_append=1 + for i in "${!COMP_WORDS[@]}" + do + if [ "$i" -ne 0 ] && [ "$i" -ne "$cword" ] + then + # disallow double long parameters + if [ "${COMP_WORDS[$i]}" == "$param" ] + then + do_append= + # disallow double short parameters + elif [ "--$(_lmms_long_param_of "${COMP_WORDS[$i]}")" == "$param" ] + then + do_append= + # --help or --version must be the first parameters + elif [ "$cword" -gt 1 ] && [[ $param =~ --help|--version ]] + then + do_append= + fi + fi + done + if [ "$do_append" ] + then + params+="$param " + fi + done + ;; + esac + + case $filemode in + + # use completion routine provided by bash-completion + # to fill $COMPREPLY + + existing_files) + _filedir "@($filetypes)" + ;; + + existing_directories) + _filedir -d + ;; + + files) + + # non existing files complete like directories... + _filedir -d + + # ...except for non-completing files with the right file type + if [ ${#COMPREPLY[@]} -eq 0 ] + then + if ! [[ "$cur" =~ /$ ]] && [ "$filetypes" ] && [[ "$cur" =~ \.($filetypes)$ ]] + then + # file ending fits, we seem to be done + COMPREPLY=( "$cur" ) + fi + fi + ;; + + esac + + if [ "$params" ] + then + # none of our parameters contain spaces, so deactivate shellcheck's warning + # shellcheck disable=SC2207 + COMPREPLY+=( $(compgen -W "${params}" -- "${cur}") ) + fi +} + +complete -F _lmms lmms diff --git a/doc/lmms.1 b/doc/lmms.1 index 1d8fa8672..a7e8be232 100644 --- a/doc/lmms.1 +++ b/doc/lmms.1 @@ -2,7 +2,7 @@ .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) -.TH LMMS 1 "June 15, 2017" +.TH LMMS 1 "September 10, 2018" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: @@ -19,125 +19,83 @@ lmms \- software for easy music production .SH SYNOPSIS .B lmms -.RB "[ \--\fBallowroot\fP ]" +.RB "[\fBglobal options...\fP] [\fBaction\fP [\fBaction parameters\fP...]] .br -.B lmms -.RB "[ \--\fBbitrate\fP \fIbitrate\fP ]" -.br -.B lmms -.RB "[ \--\fBconfig\fP \fIconfigfile\fP ]" -.br -.B lmms -.RB "[ \--\fBdump\fP \fIin\fP ]" -.br -.B lmms -.RB "[ \--\fBfloat\fP ]" -.br -.B lmms -.RB "[ \--\fBformat\fP \fIformat\fP ]" -.br -.B lmms -.RB "[ \--\fBgeometry\fP \fIgeometry\fP ]" -.br -.B lmms -.RB "[ \--\fBhelp\fP ]" -.br -.B lmms -.RB "[ \--\interpolation\fP \fImethod\fP ]" -.br -.B lmms -.RB "[ \--\fBimport\fP \fIin\fP [ \-e ] ]" -.br -.B lmms -.RB "[ \--\fBloop\fP ]" -.br -.B lmms -.RB "[ \--\fBmode\fP \fIstereomode\fP ]" -.br -.B lmms -.RB "[ \--\fBoutput\fP \fIpath\fP ]" -.br -.B lmms -.RB "[ \--\fBoversampling\fP \fIvalue\fP ]" -.br -.B lmms -.RB "[ \--\fBprofile\fP \fIout\fP ]" -.br -.B lmms -.RB "[ \--\fBrender\fP \fIfile\fP ] [options]" -.br -.B lmms -.RB "[ \--\fBsamplerate\fP \fIsamplerate\fP ]" -.br -.B lmms -.RB "[ \--\fBupgrade\fP \fIin\fP \fIout\fP ]" -.br -.B lmms -.RB "[ \--\fBversion\fP ]" -.br -.B lmms -.RI "[ file ]" .SH DESCRIPTION .PP .\" TeX users may be more comfortable with the \fB\fP and .\" \fI\fP escape sequences to invode bold face and italics, .\" respectively. .B LMMS -LMMS is a free cross-platform alternative to commercial programs like FL Studio®, which allow you to produce music with your computer. This includes the creation of melodies and beats, the synthesis and mixing of sounds, and arranging of samples. You can have fun with your MIDI-keyboard and much more; all in a user-friendly and modern interface. +is a free cross-platform alternative to commercial programs like FL Studio®, which allow you to produce music with your computer. This includes the creation of melodies and beats, the synthesis and mixing of sounds, and arranging of samples. You can have fun with your MIDI-keyboard and much more; all in a user-friendly and modern interface. LMMS features components such as a Song Editor, a Beat+Bassline Editor, a Piano Roll, an FX Mixer as well as many powerful instruments and effects. -.SH OPTIONS -.IP "\fB\-a, --float\fP -32bit float bit depth -.IP "\fB\-b, --bitrate\fP \fIbitrate\fP -Specify output bitrate in KBit/s (for OGG encoding only), default is 160 +.SH ACTIONS + +.IP " [\fIoptions\fP...] [\fIproject\fP] +Start LMMS in normal GUI mode. +.IP "\fBdump\fP \fIin\fP +Dump XML of compressed (MMPZ) file \fIin\fP. +.IP "\fBrender\fP \fIproject\fP [\fIoptions\fP...] +Render given project file. +.IP "\fBrendertracks\fP \fIproject\fP [\fIoptions\fP...] +Render each track to a different file. +.IP "\fBupgrade\fP \fIin\fP [\fIout\fP] +Upgrade file \fIin\fP and save as \fIout\fP. Standard out is used if no output file is specifed. + +.SH GLOBAL OPTIONS + +.IP "\fB\ --allowroot +Bypass root user startup check (use with caution). .IP "\fB\-c, --config\fP \fIconfigfile\fP -Get the configuration from \fIconfigfile\fP instead of ~/.lmmsrc.xml (default) -.IP "\fB\-d, --dump\fP \fIin\fP -Dump XML of compressed file \fIin\fP (i.e. MMPZ-file) -.IP "\fB\-f, --format\fP \fIformat\fP -Specify format of render-output where \fIformat\fP is either 'wav', 'flac', 'ogg' or 'mp3'. -.IP "\fB\ --geometry\fP \fIgeometry\fP -Specify the prefered size and position of the main window -.br -\fIgeometry\fP syntax is <\fIxsize\fPx\fIysize\fP+\fIxoffset\fP+\fIyoffset\fP>. -.br -Default: full screen +Get the configuration from \fIconfigfile\fP instead of ~/.lmmsrc.xml (default). .IP "\fB\-h, --help\fP Show usage information and exit. -.IP "\fB\-i, --interpolation\fP \fImethod\fP -Specify interpolation method - possible values are \fIlinear\fP, \fIsincfastest\fP (default), \fIsincmedium\fP, \fIsincbest\fP -.IP "\fB\ --import\fP \fIin\fP \fB\-e\fP -Import MIDI file \fIin\fP +.IP "\fB\-v, --version +Show version information and exit. + +.SH OPTIONS IF NO ACTION IS GIVEN + +.IP "\fB\ --geometry\fP \fIgeometry\fP +Specify the prefered size and position of the main window. .br +\fIgeometry\fP syntax is \fIxsize\fPx\fIysize\fP+\fIxoffset\fP+\fIyoffset\fP. +.br +Default: full screen. +.IP "\fB\ --import\fP \fIin\fP \fB\-e\fP +Import MIDI or Hydrogen file \fIin\fP. +.br + +.SH OPTIONS FOR RENDER AND RENDERTRACKS + +.IP "\fB\-a, --float\fP +Use 32bit float bit depth. +.IP "\fB\-b, --bitrate\fP \fIbitrate\fP +Specify output bitrate in KBit/s (for OGG encoding only), default is 160. +.IP "\fB\-f, --format\fP \fIformat\fP +Specify format of render-output where \fIformat\fP is either 'wav', 'flac', 'ogg' or 'mp3'. +.IP "\fB\-i, --interpolation\fP \fImethod\fP +Specify interpolation method - possible values are \fIlinear\fP, \fIsincfastest\fP (default), \fIsincmedium\fP, \fIsincbest\fP. + If -e is specified lmms exits after importing the file. .IP "\fB\-l, --loop Render the given file as a loop, i.e. stop rendering at exactly the end of the song. Additional silence or reverb tails at the end of the song are not rendered. .IP "\fB\-m, --mode\fP \fIstereomode\fP Set the stereo mode used for the MP3 export. \fIstereomode\fP can be either 's' (stereo mode), 'j' (joint stereo) or 'm' (mono). If no mode is given 'j' is used as the default. .IP "\fB\-o, --output\fP \fIpath\fP -Render into \fIpath\fP +Render into \fIpath\fP. .br For --render, this is interpreted as a file path. .br For --render-tracks, this is interpreted as a path to an existing directory. -IP "\fB\-p, --profile\fP \fIout\fP -Dump profiling information to file \fIout\fP -.IP "\fB\-r, --render\fP \fIproject-file\fP -Render given file to either a wav\- or ogg\-file. See \fB\-f\fP for details -.IP "\fB\-r, --rendertracks\fP \fIproject-file\fP -Render each track into a separate wav\- or ogg\-file. See \fB\-f\fP for details +.IP "\fB\-p, --profile\fP \fIout\fP +Dump profiling information to file \fIout\fP. .IP "\fB\-s, --samplerate\fP \fIsamplerate\fP -Specify output samplerate in Hz - range is 44100 (default) to 192000 -.IP "\fB\-u, --upgrade\fP \fIin\fP \fIout\fP -Upgrade file \fIin\fP and save as \fIout\fP -.IP "\fB\-v, --version -Show version information and exit. +Specify output samplerate in Hz - range is 44100 (default) to 192000. .IP "\fB\-x, --oversampling\fP \fIvalue\fP -Specify oversampling, possible values: 1, 2 (default), 4, 8 -.IP "\fB\ --allowroot -Bypass root user startup check (use with caution). +Specify oversampling, possible values: 1, 2 (default), 4, 8. + .SH SEE ALSO .BR https://lmms.io/ .BR https://lmms.io/documentation/ diff --git a/doc/wiki b/doc/wiki new file mode 160000 index 000000000..19179c6f6 --- /dev/null +++ b/doc/wiki @@ -0,0 +1 @@ +Subproject commit 19179c6f6afb422cf8376ed3b4a498a6396fc12f 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/AudioFileDevice.h b/include/AudioFileDevice.h index 7b6b81eab..e7177b30f 100644 --- a/include/AudioFileDevice.h +++ b/include/AudioFileDevice.h @@ -56,6 +56,10 @@ protected: return m_outputFile.isOpen(); } + inline int outputFileHandle() const + { + return m_outputFile.handle(); + } private: QFile m_outputFile; 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/AudioJack.h b/include/AudioJack.h index 83717f251..c3207c829 100644 --- a/include/AudioJack.h +++ b/include/AudioJack.h @@ -37,7 +37,6 @@ #include #include #include -#include #include "AudioDevice.h" #include "AudioDeviceSetupWidget.h" @@ -108,7 +107,6 @@ private: bool m_active; bool m_stopped; - QMutex m_processingMutex; MidiJack *m_midiClient; QVector m_outputPorts; 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/AudioPortAudio.h b/include/AudioPortAudio.h index 6a07aad47..e1288c3a4 100644 --- a/include/AudioPortAudio.h +++ b/include/AudioPortAudio.h @@ -34,6 +34,7 @@ class AudioPortAudioSetupUtil : public QObject { Q_OBJECT public slots: + void updateBackends(); void updateDevices(); void updateChannels(); @@ -87,6 +88,7 @@ public: virtual ~setupWidget(); virtual void saveSettings(); + virtual void show(); private: ComboBox * m_backend; @@ -145,7 +147,6 @@ private: int m_outBufSize; bool m_stopped; - QSemaphore m_stopSemaphore; } ; 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 11942efda..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,24 +71,42 @@ 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 ); +#ifdef LMMS_HAVE_SDL2 + static void sdlInputAudioCallback( void * _udata, Uint8 * _buf, int _len ); + void sdlInputAudioCallback( Uint8 * _buf, int _len ); +#endif + SDL_AudioSpec m_audioHandle; surroundSampleFrame * m_outBuf; + +#ifdef LMMS_HAVE_SDL2 + size_t m_currentBufferFramePos; + size_t m_currentBufferFramesCount; +#else Uint8 * m_convertedBuf; int m_convertedBufPos; int m_convertedBufSize; + bool m_outConvertEndian; +#endif - bool m_convertEndian; bool m_stopped; +#ifdef LMMS_HAVE_SDL2 + SDL_AudioDeviceID m_outputDevice; + + SDL_AudioSpec m_inputAudioHandle; + SDL_AudioDeviceID m_inputDevice; +#endif + } ; #endif 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/AudioSoundIo.h b/include/AudioSoundIo.h index b0192a19e..f743ad676 100644 --- a/include/AudioSoundIo.h +++ b/include/AudioSoundIo.h @@ -109,6 +109,8 @@ private: fpp_t m_outBufFramesTotal; fpp_t m_outBufFrameIndex; + bool m_stopped; + int m_disconnectErr; void onBackendDisconnect(int err); diff --git a/include/AutomatableButton.h b/include/AutomatableButton.h index 014f1eed8..d7859a10c 100644 --- a/include/AutomatableButton.h +++ b/include/AutomatableButton.h @@ -34,12 +34,12 @@ class automatableButtonGroup; -class EXPORT AutomatableButton : public QPushButton, public BoolModelView +class LMMS_EXPORT AutomatableButton : public QPushButton, public BoolModelView { Q_OBJECT public: AutomatableButton( QWidget * _parent, const QString & _name - = QString::null ); + = QString() ); virtual ~AutomatableButton(); inline void setCheckable( bool _on ) @@ -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: @@ -79,12 +79,12 @@ private: -class EXPORT automatableButtonGroup : public QWidget, public IntModelView +class LMMS_EXPORT automatableButtonGroup : public QWidget, public IntModelView { Q_OBJECT public: automatableButtonGroup( QWidget * _parent, const QString & _name - = QString::null ); + = QString() ); virtual ~automatableButtonGroup(); void addButton( AutomatableButton * _btn ); @@ -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 b04f3da9c..6d8000804 100644 --- a/include/AutomatableModel.h +++ b/include/AutomatableModel.h @@ -33,6 +33,7 @@ #include "MidiTime.h" #include "ValueBuffer.h" #include "MemoryManager.h" +#include "ModelVisitor.h" // simple way to map a property of a view to a model #define mapPropertyFromModelPtr(type,getfunc,setfunc,modelname) \ @@ -59,15 +60,21 @@ modelname.setValue( (float) val ); \ } +// use this to make subclasses visitable +#define MODEL_IS_VISITABLE \ + void accept(ModelVisitor& v) override { v.visit(*this); } \ + void accept(ConstModelVisitor& v) const override { v.visit(*this); } + class ControllerConnection; -class EXPORT AutomatableModel : public Model, public JournallingObject +class LMMS_EXPORT AutomatableModel : public Model, public JournallingObject { Q_OBJECT MM_OPERATORS public: + typedef QVector AutoModelVector; enum ScaleType @@ -80,6 +87,35 @@ public: virtual ~AutomatableModel(); + // Implement those by using the MODEL_IS_VISITABLE macro + virtual void accept(ModelVisitor& v) = 0; + virtual void accept(ConstModelVisitor& v) const = 0; + +public: + /** + @brief Return this class casted to Target + @test AutomatableModelTest.cpp + @param doThrow throw an assertion if the cast fails, instead of + returning a nullptr + @return the casted class if Target is the exact or a base class of + *this, nullptr otherwise + */ + template + Target* dynamicCast(bool doThrow = false) + { + DCastVisitor vis; accept(vis); + if (doThrow && !vis.result) { Q_ASSERT(false); } + return vis.result; + } + + //! const overload, see overloaded function + template + const Target* dynamicCast(bool doThrow = false) const + { + ConstDCastVisitor vis; accept(vis); + if (doThrow && !vis.result) { Q_ASSERT(false); } + return vis.result; + } bool isAutomated() const; bool isAutomatedOrControlled() const @@ -219,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"; } @@ -283,12 +319,30 @@ protected: private: - virtual void saveSettings( QDomDocument& doc, QDomElement& element ) + // dynamicCast implementation + template + struct DCastVisitor : public ModelVisitor + { + Target* result = nullptr; + void visit(Target& tar) { result = &tar; } + }; + + // dynamicCast implementation + template + struct ConstDCastVisitor : public ConstModelVisitor + { + const Target* result = nullptr; + void visit(const Target& tar) { result = &tar; } + }; + + static bool mustQuoteName(const QString &name); + + 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" ); } @@ -349,7 +403,7 @@ signals: -template class EXPORT TypedAutomatableModel : public AutomatableModel +template class LMMS_EXPORT TypedAutomatableModel : public AutomatableModel { public: using AutomatableModel::AutomatableModel; @@ -377,9 +431,10 @@ public: // some typed AutomatableModel-definitions -class EXPORT FloatModel : public TypedAutomatableModel +class LMMS_EXPORT FloatModel : public TypedAutomatableModel { Q_OBJECT + MODEL_IS_VISITABLE public: FloatModel( float val = 0, float min = 0, float max = 0, float step = 0, Model * parent = NULL, @@ -394,9 +449,10 @@ public: } ; -class EXPORT IntModel : public TypedAutomatableModel +class LMMS_EXPORT IntModel : public TypedAutomatableModel { Q_OBJECT + MODEL_IS_VISITABLE public: IntModel( int val = 0, int min = 0, int max = 0, Model* parent = NULL, @@ -409,9 +465,10 @@ public: } ; -class EXPORT BoolModel : public TypedAutomatableModel +class LMMS_EXPORT BoolModel : public TypedAutomatableModel { Q_OBJECT + MODEL_IS_VISITABLE public: BoolModel( const bool val = false, Model* parent = NULL, diff --git a/include/AutomatableModelView.h b/include/AutomatableModelView.h index 3b320434f..1bcbd97d6 100644 --- a/include/AutomatableModelView.h +++ b/include/AutomatableModelView.h @@ -32,7 +32,7 @@ class QMenu; class QMouseEvent; -class EXPORT AutomatableModelView : public ModelView +class LMMS_EXPORT AutomatableModelView : public ModelView { public: AutomatableModelView( Model* model, QWidget* _this ); @@ -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 @@ -106,7 +106,7 @@ protected: -template class EXPORT TypedModelView : public AutomatableModelView +template class LMMS_EXPORT TypedModelView : public AutomatableModelView { public: TypedModelView( Model* model, QWidget* _this) : @@ -127,6 +127,5 @@ using FloatModelView = TypedModelView; using IntModelView = TypedModelView; using BoolModelView = TypedModelView; - #endif diff --git a/include/AutomatableSlider.h b/include/AutomatableSlider.h index 0fbd3adf6..b51ef1e3f 100644 --- a/include/AutomatableSlider.h +++ b/include/AutomatableSlider.h @@ -36,7 +36,7 @@ class AutomatableSlider : public QSlider, public IntModelView { Q_OBJECT public: - AutomatableSlider( QWidget * _parent, const QString & _name = QString::null ); + AutomatableSlider( QWidget * _parent, const QString & _name = QString() ); virtual ~AutomatableSlider(); bool showStatus() @@ -51,12 +51,12 @@ signals: protected: - virtual void contextMenuEvent( QContextMenuEvent * _me ); - virtual void mousePressEvent( QMouseEvent * _me ); - virtual void mouseReleaseEvent( QMouseEvent * _me ); - virtual void wheelEvent( QWheelEvent * _me ); + void contextMenuEvent( QContextMenuEvent * _me ) override; + void mousePressEvent( QMouseEvent * _me ) override; + void mouseReleaseEvent( QMouseEvent * _me ) override; + void wheelEvent( QWheelEvent * _me ) override; - virtual void modelChanged(); + void modelChanged() override; private: diff --git a/include/AutomationEditor.h b/include/AutomationEditor.h index 9705c5efa..60b894f1f 100644 --- a/include/AutomationEditor.h +++ b/include/AutomationEditor.h @@ -73,9 +73,9 @@ public: return m_pattern != nullptr; } - virtual void saveSettings(QDomDocument & doc, QDomElement & parent); - virtual void loadSettings(const QDomElement & parent); - QString nodeName() const + void saveSettings(QDomDocument & doc, QDomElement & parent) override; + void loadSettings(const QDomElement & parent) override; + QString nodeName() const override { return "automationeditor"; } @@ -114,14 +114,14 @@ public slots: protected: typedef AutomationPattern::timeMap timeMap; - virtual void keyPressEvent(QKeyEvent * ke); - virtual void leaveEvent(QEvent * e); - virtual void mousePressEvent(QMouseEvent * mouseEvent); - virtual void mouseReleaseEvent(QMouseEvent * mouseEvent); - virtual void mouseMoveEvent(QMouseEvent * mouseEvent); - virtual void paintEvent(QPaintEvent * pe); - virtual void resizeEvent(QResizeEvent * re); - virtual void wheelEvent(QWheelEvent * we); + void keyPressEvent(QKeyEvent * ke) override; + void leaveEvent(QEvent * e) override; + void mousePressEvent(QMouseEvent * mouseEvent) override; + void mouseReleaseEvent(QMouseEvent * mouseEvent) override; + void mouseMoveEvent(QMouseEvent * mouseEvent) override; + void paintEvent(QPaintEvent * pe) override; + void resizeEvent(QResizeEvent * re) override; + void wheelEvent(QWheelEvent * we) override; float getLevel( int y ); int xCoordOfTick( int tick ); @@ -176,8 +176,8 @@ private: static const int TOP_MARGIN = 16; static const int DEFAULT_Y_DELTA = 6; - static const int DEFAULT_STEPS_PER_TACT = 16; - static const int DEFAULT_PPT = 12 * DEFAULT_STEPS_PER_TACT; + static const int DEFAULT_STEPS_PER_BAR = 16; + static const int DEFAULT_PPB = 12 * DEFAULT_STEPS_PER_BAR; static const int VALUES_WIDTH = 64; @@ -230,7 +230,7 @@ private: float m_drawLastLevel; tick_t m_drawLastTick; - int m_ppt; + int m_ppb; int m_y_delta; bool m_y_auto; @@ -282,14 +282,14 @@ public: void setCurrentPattern(AutomationPattern* pattern); const AutomationPattern* currentPattern(); - virtual void dropEvent( QDropEvent * _de ); - virtual void dragEnterEvent( QDragEnterEvent * _dee ); + void dropEvent( QDropEvent * _de ) override; + void dragEnterEvent( QDragEnterEvent * _dee ) override; void open(AutomationPattern* pattern); AutomationEditor* m_editor; - QSize sizeHint() const; + QSize sizeHint() const override; public slots: void clearCurrentPattern(); @@ -297,9 +297,12 @@ public slots: signals: void currentPatternChanged(); +protected: + void focusInEvent(QFocusEvent * event) override; + protected slots: - void play(); - void stop(); + void play() override; + void stop() override; private slots: void updateWindowTitle(); diff --git a/include/AutomationPattern.h b/include/AutomationPattern.h index 89dcfed7c..cad9d0a1d 100644 --- a/include/AutomationPattern.h +++ b/include/AutomationPattern.h @@ -38,7 +38,7 @@ class MidiTime; -class EXPORT AutomationPattern : public TrackContentObject +class LMMS_EXPORT AutomationPattern : public TrackContentObject { Q_OBJECT public: @@ -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 9e72c4f04..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: @@ -125,7 +125,7 @@ private: -class EXPORT BBTrack : public Track +class LMMS_EXPORT BBTrack : public Track { Q_OBJECT public: @@ -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 0ac84b6d3..17d6eb5fe 100644 --- a/include/BBTrackContainer.h +++ b/include/BBTrackContainer.h @@ -30,7 +30,7 @@ #include "ComboBoxModel.h" -class EXPORT BBTrackContainer : public TrackContainer +class LMMS_EXPORT BBTrackContainer : public TrackContainer { Q_OBJECT mapPropertyFromModel(int,currentBB,setCurrentBB,m_bbComboBoxModel); @@ -41,15 +41,15 @@ public: virtual bool play( MidiTime _start, const fpp_t _frames, const f_cnt_t _frame_base, int _tco_num = -1 ); - virtual void updateAfterTrackAdd() override; + void updateAfterTrackAdd() override; - inline virtual QString nodeName() const override + inline QString nodeName() const override { return "bbtrackcontainer"; } - tact_t lengthOfBB( int _bb ) const; - inline tact_t lengthOfCurrentBB() + bar_t lengthOfBB( int _bb ) const; + inline bar_t lengthOfCurrentBB() { return lengthOfBB( currentBB() ); } diff --git a/include/BandLimitedWave.h b/include/BandLimitedWave.h index 55f6e482c..386713328 100644 --- a/include/BandLimitedWave.h +++ b/include/BandLimitedWave.h @@ -29,7 +29,7 @@ class QDataStream; class QString; -#include "export.h" +#include "lmms_export.h" #include "interpolation.h" #include "lmms_basics.h" #include "lmms_math.h" @@ -82,7 +82,7 @@ QDataStream& operator>> ( QDataStream &in, WaveMipMap &waveMipMap ); -class EXPORT BandLimitedWave +class LMMS_EXPORT BandLimitedWave { public: enum Waveforms diff --git a/include/BasicFilters.h b/include/BasicFilters.h index 684596c4d..c3a76d36e 100644 --- a/include/BasicFilters.h +++ b/include/BasicFilters.h @@ -39,7 +39,6 @@ #include #include "lmms_basics.h" -#include "templates.h" #include "lmms_constants.h" #include "interpolation.h" #include "MemoryManager.h" diff --git a/include/BufferManager.h b/include/BufferManager.h index 97c553ac9..20390644b 100644 --- a/include/BufferManager.h +++ b/include/BufferManager.h @@ -26,10 +26,10 @@ #ifndef BUFFER_MANAGER_H #define BUFFER_MANAGER_H -#include "export.h" +#include "lmms_export.h" #include "lmms_basics.h" -class EXPORT BufferManager +class LMMS_EXPORT BufferManager { public: static void init( fpp_t framesPerPeriod ); 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/CaptionMenu.h b/include/CaptionMenu.h index 01aa3ca5e..e6531fe31 100644 --- a/include/CaptionMenu.h +++ b/include/CaptionMenu.h @@ -28,12 +28,12 @@ #include -#include "export.h" +#include "lmms_export.h" /// /// \brief A context menu with a caption /// -class EXPORT CaptionMenu : public QMenu +class LMMS_EXPORT CaptionMenu : public QMenu { Q_OBJECT public: diff --git a/include/ComboBox.h b/include/ComboBox.h index 99f7f8750..d530c9d92 100644 --- a/include/ComboBox.h +++ b/include/ComboBox.h @@ -34,7 +34,7 @@ -class EXPORT ComboBox : public QWidget, public IntModelView +class LMMS_EXPORT ComboBox : public QWidget, public IntModelView { Q_OBJECT public: @@ -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/ComboBoxModel.h b/include/ComboBoxModel.h index e4088679f..82c01e69e 100644 --- a/include/ComboBoxModel.h +++ b/include/ComboBoxModel.h @@ -33,9 +33,10 @@ #include "embed.h" -class EXPORT ComboBoxModel : public IntModel +class LMMS_EXPORT ComboBoxModel : public IntModel { Q_OBJECT + MODEL_IS_VISITABLE public: ComboBoxModel( Model* parent = NULL, const QString& displayName = QString(), diff --git a/include/ConfigManager.h b/include/ConfigManager.h index 997d7f24c..556c455a0 100644 --- a/include/ConfigManager.h +++ b/include/ConfigManager.h @@ -34,7 +34,8 @@ #include #include -#include "export.h" +#include "lmms_export.h" + class LmmsCore; @@ -51,67 +52,28 @@ const QString TRACK_ICON_PATH = "track_icons/"; const QString LOCALE_PATH = "locale/"; -class EXPORT ConfigManager : public QObject +class LMMS_EXPORT ConfigManager : public QObject { Q_OBJECT public: static inline ConfigManager * inst() { - if( s_instanceOfMe == NULL ) + if(s_instanceOfMe == NULL ) { s_instanceOfMe = new ConfigManager(); } return s_instanceOfMe; } - const QString & dataDir() const - { - return m_dataDir; - } const QString & workingDir() const { return m_workingDir; } - QString userProjectsDir() const + const QString & dataDir() const { - return workingDir() + PROJECTS_PATH; - } - - QString userTemplateDir() const - { - return workingDir() + TEMPLATE_PATH; - } - - QString userPresetsDir() const - { - return workingDir() + PRESETS_PATH; - } - - QString userSamplesDir() const - { - return workingDir() + SAMPLES_PATH; - } - - QString userGigDir() const - { - return workingDir() + GIG_PATH; - } - - QString userSf2Dir() const - { - return workingDir() + SF2_PATH; - } - - QString userLadspaDir() const - { - return workingDir() + LADSPA_PATH; - } - - QString userVstDir() const - { - return m_vstDir; + return m_dataDir; } QString factoryProjectsDir() const @@ -134,37 +96,27 @@ public: return dataDir() + SAMPLES_PATH; } - QString defaultVersion() const; - QString defaultArtworkDir() const + QString userProjectsDir() const { - return m_dataDir + DEFAULT_THEME_PATH; + return workingDir() + PROJECTS_PATH; } - QString artworkDir() const + QString userTemplateDir() const { - return m_artworkDir; + return workingDir() + TEMPLATE_PATH; } - QString trackIconsDir() const + QString userPresetsDir() const { - return m_dataDir + TRACK_ICON_PATH; + return workingDir() + PRESETS_PATH; } - QString localeDir() const + QString userSamplesDir() const { - return m_dataDir + LOCALE_PATH; + return workingDir() + SAMPLES_PATH; } - const QString & gigDir() const - { - return m_gigDir; - } - - const QString & sf2Dir() const - { - return m_sf2Dir; - } const QString & vstDir() const { @@ -173,18 +125,20 @@ public: const QString & ladspaDir() const { - return m_ladDir; + return m_ladspaDir; } - const QString recoveryFile() const + const QString & sf2Dir() const { - return m_workingDir + "recover.mmp"; + return m_sf2Dir; } - - const QString & version() const + +#ifdef LMMS_HAVE_FLUIDSYNTH + const QString & sf2File() const { - return m_version; + return m_sf2File; } +#endif #ifdef LMMS_HAVE_STK const QString & stkDir() const @@ -193,16 +147,55 @@ public: } #endif -#ifdef LMMS_HAVE_FLUIDSYNTH - const QString & defaultSoundfont() const + const QString & gigDir() const { - return m_defaultSoundfont; + return m_gigDir; } -#endif - const QString & backgroundArtwork() const + + QString userVstDir() const { - return m_backgroundArtwork; + return m_vstDir; + } + + QString userLadspaDir() const + { + return workingDir() + LADSPA_PATH; + } + + QString userSf2Dir() const + { + return workingDir() + SF2_PATH; + } + + QString userGigDir() const + { + return workingDir() + GIG_PATH; + } + + QString defaultThemeDir() const + { + return m_dataDir + DEFAULT_THEME_PATH; + } + + QString themeDir() const + { + return m_themeDir; + } + + const QString & backgroundPicFile() const + { + return m_backgroundPicFile; + } + + QString trackIconsDir() const + { + return m_dataDir + TRACK_ICON_PATH; + } + + const QString recoveryFile() const + { + return m_workingDir + "recover.mmp"; } inline const QStringList & recentlyOpenedProjects() const @@ -210,39 +203,51 @@ public: return m_recentlyOpenedProjects; } + QString localeDir() const + { + return m_dataDir + LOCALE_PATH; + } + + const QString & version() const + { + return m_version; + } + + QString defaultVersion() const; + + static QStringList availabeVstEmbedMethods(); QString vstEmbedMethod() const; - // returns true if the working dir (e.g. ~/lmms) exists on disk + // Returns true if the working dir (e.g. ~/lmms) exists on disk. bool hasWorkingDir() const; - void addRecentlyOpenedProject( const QString & _file ); + void addRecentlyOpenedProject(const QString & _file); - const QString & value( const QString & cls, - const QString & attribute ) const; - const QString & value( const QString & cls, + const QString & value(const QString & cls, + const QString & attribute) const; + const QString & value(const QString & cls, const QString & attribute, - const QString & defaultVal ) const; - void setValue( const QString & cls, const QString & attribute, - const QString & value ); - void deleteValue( const QString & cls, const QString & attribute); + const QString & defaultVal) const; + void setValue(const QString & cls, const QString & attribute, + const QString & value); + void deleteValue(const QString & cls, const QString & attribute); - void loadConfigFile( const QString & configFile = "" ); + void loadConfigFile(const QString & configFile = ""); void saveConfigFile(); - void setWorkingDir( const QString & _wd ); - void setVSTDir( const QString & _vd ); - void setArtworkDir( const QString & _ad ); - void setLADSPADir( const QString & _fd ); - void setVersion( const QString & _cv ); - void setSTKDir( const QString & _fd ); - void setDefaultSoundfont( const QString & _sf ); - void setBackgroundArtwork( const QString & _ba ); - void setGIGDir( const QString & gd ); - void setSF2Dir( const QString & sfd ); + void setWorkingDir(const QString & workingDir); + void setVSTDir(const QString & vstDir); + void setLADSPADir(const QString & ladspaDir); + void setSF2Dir(const QString & sf2Dir); + void setSF2File(const QString & sf2File); + void setSTKDir(const QString & stkDir); + void setGIGDir(const QString & gigDir); + void setThemeDir(const QString & themeDir); + void setBackgroundPicFile(const QString & backgroundPicFile); - // creates the working directory & subdirectories on disk. + // Creates the working directory & subdirectories on disk. void createWorkingDir(); signals: @@ -252,29 +257,29 @@ private: static ConfigManager * s_instanceOfMe; ConfigManager(); - ConfigManager( const ConfigManager & _c ); + ConfigManager(const ConfigManager & _c); ~ConfigManager(); void upgrade_1_1_90(); void upgrade_1_1_91(); void upgrade(); - QString m_lmmsRcFile; QString m_workingDir; QString m_dataDir; - QString m_artworkDir; QString m_vstDir; - QString m_ladDir; - QString m_gigDir; + QString m_ladspaDir; QString m_sf2Dir; - QString m_version; +#ifdef LMMS_HAVE_FLUIDSYNTH + QString m_sf2File; +#endif #ifdef LMMS_HAVE_STK QString m_stkDir; #endif -#ifdef LMMS_HAVE_FLUIDSYNTH - QString m_defaultSoundfont; -#endif - QString m_backgroundArtwork; + QString m_gigDir; + QString m_themeDir; + QString m_backgroundPicFile; + QString m_lmmsRcFile; + QString m_version; QStringList m_recentlyOpenedProjects; typedef QVector > stringPairVector; @@ -283,7 +288,5 @@ private: friend class LmmsCore; - -} ; - +}; #endif diff --git a/include/Controller.h b/include/Controller.h index 89a5e9371..b60349463 100644 --- a/include/Controller.h +++ b/include/Controller.h @@ -27,11 +27,10 @@ #ifndef CONTROLLER_H #define CONTROLLER_H -#include "export.h" +#include "lmms_export.h" #include "Engine.h" #include "Model.h" #include "JournallingObject.h" -#include "templates.h" #include "ValueBuffer.h" class ControllerDialog; @@ -41,7 +40,7 @@ class ControllerConnection; typedef QVector ControllerVector; -class EXPORT Controller : public Model, public JournallingObject +class LMMS_EXPORT Controller : public Model, public JournallingObject { Q_OBJECT public: @@ -102,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, @@ -112,7 +111,7 @@ public: inline static float fittedValue( float _val ) { - return tLimit( _val, 0.0f, 1.0f ); + return qBound( 0.0f, _val, 1.0f ); } static long runningPeriods() diff --git a/include/ControllerConnection.h b/include/ControllerConnection.h index e9cd543cb..e57cd4db2 100644 --- a/include/ControllerConnection.h +++ b/include/ControllerConnection.h @@ -42,7 +42,7 @@ class ControllerConnection; typedef QVector ControllerConnectionVector; -class EXPORT ControllerConnection : public QObject, public JournallingObject +class LMMS_EXPORT ControllerConnection : public QObject, public JournallingObject { Q_OBJECT public: @@ -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/DataFile.h b/include/DataFile.h index 9e4ca13e3..5890693da 100644 --- a/include/DataFile.h +++ b/include/DataFile.h @@ -29,12 +29,12 @@ #include -#include "export.h" +#include "lmms_export.h" #include "MemoryManager.h" class QTextStream; -class EXPORT DataFile : public QDomDocument +class LMMS_EXPORT DataFile : public QDomDocument { MM_OPERATORS public: @@ -84,25 +84,6 @@ public: return m_type; } - // small helper class for adjusting application's locale settings - // when loading or saving floating point values rendered to strings - class LocaleHelper - { - public: - enum Modes - { - ModeLoad, - ModeSave, - ModeCount - }; - typedef Modes Mode; - - LocaleHelper( Mode mode ); - ~LocaleHelper(); - - }; - - private: static Type type( const QString& typeName ); static QString typeName( Type type ); @@ -134,7 +115,7 @@ private: void loadData( const QByteArray & _data, const QString & _sourceFile ); - struct EXPORT typeDescStruct + struct LMMS_EXPORT typeDescStruct { Type m_type; QString m_name; 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/DrumSynth.h b/include/DrumSynth.h index 22d7d3071..f7e9b1d4c 100644 --- a/include/DrumSynth.h +++ b/include/DrumSynth.h @@ -30,22 +30,24 @@ #include #include "lmms_basics.h" +class QString; + class DrumSynth { public: DrumSynth() {}; - int GetDSFileSamples(const char *dsfile, int16_t *&wave, int channels, sample_rate_t Fs); + int GetDSFileSamples(QString dsfile, int16_t *&wave, int channels, sample_rate_t Fs); private: float LoudestEnv(void); int LongestEnv(void); void UpdateEnv(int e, long t); - void GetEnv(int env, const char *sec, const char *key, const char *ini); + void GetEnv(int env, const char *sec, const char *key, QString ini); float waveform(float ph, int form); - int GetPrivateProfileString(const char *sec, const char *key, const char *def, char *buffer, int size, const char *file); - int GetPrivateProfileInt(const char *sec, const char *key, int def, const char *file); - float GetPrivateProfileFloat(const char *sec, const char *key, float def, const char *file); + int GetPrivateProfileString(const char *sec, const char *key, const char *def, char *buffer, int size, QString file); + int GetPrivateProfileInt(const char *sec, const char *key, int def, QString file); + float GetPrivateProfileFloat(const char *sec, const char *key, float def, QString file); }; diff --git a/include/DspEffectLibrary.h b/include/DspEffectLibrary.h index 76296da0b..bf175df6d 100644 --- a/include/DspEffectLibrary.h +++ b/include/DspEffectLibrary.h @@ -27,7 +27,6 @@ #define DSP_EFFECT_LIBRARY_H #include "lmms_math.h" -#include "templates.h" #include "lmms_constants.h" #include "lmms_basics.h" 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 b69594b00..a37b089ae 100644 --- a/include/DummyInstrument.h +++ b/include/DummyInstrument.h @@ -47,28 +47,28 @@ 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 InstrumentView( this, _parent ); + 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 4b9017e9e..1c80e9f2f 100644 --- a/include/Editor.h +++ b/include/Editor.h @@ -47,10 +47,12 @@ protected: DropToolBar * addDropToolBar(Qt::ToolBarArea whereToAdd, QString const & windowTitle); DropToolBar * addDropToolBar(QWidget * parent, Qt::ToolBarArea whereToAdd, QString const & windowTitle); + void closeEvent( QCloseEvent * _ce ) override; protected slots: virtual void play() {} virtual void record() {} virtual void recordAccompany() {} + virtual void toggleStepRecording() {} virtual void stop() {} private slots: @@ -64,7 +66,7 @@ protected: /// /// \param record If set true, the editor's toolbar will contain record /// buttons in addition to the play and stop buttons. - Editor(bool record = false); + Editor(bool record = false, bool record_step = false); virtual ~Editor(); @@ -73,6 +75,7 @@ protected: QAction* m_playAction; QAction* m_recordAction; QAction* m_recordAccompanyAction; + QAction* m_toggleStepRecordingAction; QAction* m_stopAction; }; @@ -89,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 2147ab1c5..3874aa602 100644 --- a/include/Effect.h +++ b/include/Effect.h @@ -37,7 +37,7 @@ class EffectChain; class EffectControls; -class EXPORT Effect : public Plugin +class LMMS_EXPORT Effect : public Plugin { MM_OPERATORS Q_OBJECT @@ -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"; } @@ -148,11 +148,6 @@ public: m_noRun = _state; } - inline const Descriptor::SubPluginFeatures::Key & key() const - { - return m_key; - } - EffectChain * effectChain() const { return m_parent; @@ -166,9 +161,16 @@ public: protected: + /** + Effects should call this at the end of audio processing + + If the setting "Keep effects running even without input" is disabled, + after "decay" ms of a signal below "gate", the effect is turned off + and won't be processed again until it receives new audio input + */ 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 @@ -201,8 +203,6 @@ private: sampleFrame * _dst_buf, sample_rate_t _dst_sr, const f_cnt_t _frames ); - Descriptor::SubPluginFeatures::Key m_key; - ch_cnt_t m_processors; bool m_okay; diff --git a/include/EffectChain.h b/include/EffectChain.h index 5397fe81c..9ebc4d534 100644 --- a/include/EffectChain.h +++ b/include/EffectChain.h @@ -33,17 +33,17 @@ class Effect; -class EXPORT EffectChain : public Model, public SerializingObject +class LMMS_EXPORT EffectChain : public Model, public SerializingObject { Q_OBJECT 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 d139de173..4a59489da 100644 --- a/include/EffectControlDialog.h +++ b/include/EffectControlDialog.h @@ -33,20 +33,22 @@ class EffectControls; -class EXPORT EffectControlDialog : public QWidget, public ModelView +class LMMS_EXPORT EffectControlDialog : public QWidget, public ModelView { Q_OBJECT public: EffectControlDialog( EffectControls * _controls ); virtual ~EffectControlDialog(); + virtual bool isResizable() const {return false;} + signals: void closed(); 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/Engine.h b/include/Engine.h index 2f940dfbf..f4ff72fb2 100644 --- a/include/Engine.h +++ b/include/Engine.h @@ -30,7 +30,8 @@ #include -#include "export.h" +#include "lmms_export.h" +#include "lmms_basics.h" class BBTrackContainer; class DummyTrackContainer; @@ -53,7 +54,7 @@ class Ladspa2LMMS; class LmmsCore; typedef LmmsCore Engine; -class EXPORT LmmsCore : public QObject +class LMMS_EXPORT LmmsCore : public QObject { Q_OBJECT public: @@ -100,6 +101,9 @@ public: { return s_framesPerTick; } + + static float framesPerTick(sample_rate_t sample_rate); + static void updateFramesPerTick(); static inline LmmsCore * inst() @@ -111,6 +115,9 @@ public: return s_instanceOfMe; } + static void setDndPluginKey(void* newKey); + static void* pickDndPluginKey(); + signals: void initProgress(const QString &msg); @@ -137,6 +144,7 @@ private: static DummyTrackContainer * s_dummyTC; static Ladspa2LMMS * s_ladspaManager; + static void* s_dndPluginKey; // even though most methods are static, an instance is needed for Qt slots/signals static LmmsCore * s_instanceOfMe; diff --git a/include/EnvelopeAndLfoParameters.h b/include/EnvelopeAndLfoParameters.h index 747bb94c2..0f691adb0 100644 --- a/include/EnvelopeAndLfoParameters.h +++ b/include/EnvelopeAndLfoParameters.h @@ -34,7 +34,7 @@ #include "lmms_basics.h" -class EXPORT EnvelopeAndLfoParameters : public Model, public JournallingObject +class LMMS_EXPORT EnvelopeAndLfoParameters : public Model, public JournallingObject { Q_OBJECT public: @@ -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 35416f492..3124b477b 100644 --- a/include/ExportFilter.h +++ b/include/ExportFilter.h @@ -32,7 +32,7 @@ #include "Plugin.h" -class EXPORT ExportFilter : public Plugin +class LMMS_EXPORT ExportFilter : public Plugin { public: ExportFilter( const Descriptor * _descriptor ) : Plugin( _descriptor, NULL ) {} @@ -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 95753ecea..09a4c6457 100644 --- a/include/FadeButton.h +++ b/include/FadeButton.h @@ -35,8 +35,10 @@ class FadeButton : public QAbstractButton { Q_OBJECT public: - FadeButton( const QColor & _normal_color, const QColor & - _activated_color, QWidget * _parent ); + FadeButton( const QColor & _normal_color, + const QColor & _activated_color, + const QColor & _hold_color, + QWidget * _parent ); virtual ~FadeButton(); void setActiveColor( const QColor & activated_color ); @@ -44,22 +46,30 @@ public: public slots: void activate(); + void noteEnd(); protected: - virtual void customEvent( QEvent * ); - virtual void paintEvent( QPaintEvent * _pe ); + void customEvent( QEvent * ) override; + void paintEvent( QPaintEvent * _pe ) override; private: QTime m_stateTimer; + QTime m_releaseTimer; + + // the default color of the widget QColor m_normalColor; + // the color on note play QColor m_activatedColor; + // the color after the "play" fade is done but a note is still playing + QColor m_holdColor; + int activeNotes; void signalUpdate(); + QColor fadeToColor(QColor, QColor, QTime, float); } ; #endif - diff --git a/include/Fader.h b/include/Fader.h index 80359b4c6..207215445 100644 --- a/include/Fader.h +++ b/include/Fader.h @@ -57,7 +57,7 @@ class TextFloat; -class EXPORT Fader : public QWidget, public FloatModelView +class LMMS_EXPORT Fader : public QWidget, public FloatModelView { Q_OBJECT public: @@ -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 91a58831d..9b56a8dbd 100644 --- a/include/FileBrowser.h +++ b/include/FileBrowser.h @@ -55,13 +55,13 @@ public: private slots: void reloadTree( void ); - void expandItems( QTreeWidgetItem * item=NULL ); + void expandItems( QTreeWidgetItem * item=NULL, QList expandedDirs = QList() ); // call with item=NULL to filter the entire tree bool filterItems( const QString & filter, QTreeWidgetItem * item=NULL ); void giveFocusToFilter(); private: - virtual void keyPressEvent( QKeyEvent * ke ); + void keyPressEvent( QKeyEvent * ke ) override; void addItems( const QString & path ); @@ -87,12 +87,16 @@ public: FileBrowserTreeWidget( QWidget * parent ); virtual ~FileBrowserTreeWidget() = default; + //! This method returns a QList with paths (QString's) of all directories + //! that are expanded in the tree. + QList expandedDirs( QTreeWidgetItem * item = nullptr ) const; + 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: @@ -129,13 +133,13 @@ public: void update( void ); - inline QString fullName( QString path = QString::null ) + inline QString fullName( QString path = QString() ) { - if( path == QString::null ) + if( path.isEmpty() ) { path = m_directories[0]; } - if( path != QString::null ) + if( ! path.isEmpty() ) { path += QDir::separator(); } diff --git a/include/FileDialog.h b/include/FileDialog.h index 0cade9967..c3db2393d 100644 --- a/include/FileDialog.h +++ b/include/FileDialog.h @@ -28,9 +28,9 @@ #include -#include "export.h" +#include "lmms_export.h" -class EXPORT FileDialog : public QFileDialog +class LMMS_EXPORT FileDialog : public QFileDialog { Q_OBJECT public: diff --git a/include/FxLine.h b/include/FxLine.h index 6024026bd..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,9 +79,7 @@ public: static const int FxLineHeight; - void renameChannel(); - - 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 ); @@ -101,6 +99,9 @@ private: QLineEdit * m_renameLineEdit; QGraphicsView * m_view; +public slots: + void renameChannel(); + private slots: void renameFinished(); void removeChannel(); diff --git a/plugins/SpectrumAnalyzer/SpectrumAnalyzerControlDialog.h b/include/FxLineLcdSpinBox.h similarity index 56% rename from plugins/SpectrumAnalyzer/SpectrumAnalyzerControlDialog.h rename to include/FxLineLcdSpinBox.h index 17e2f7724..eeb104c5c 100644 --- a/plugins/SpectrumAnalyzer/SpectrumAnalyzerControlDialog.h +++ b/include/FxLineLcdSpinBox.h @@ -1,7 +1,7 @@ /* - * SpectrumAnalyzerControlDialog.h - view for spectrum analyzer + * FxLineLcdSpinBox.h - a specialization of LcdSpnBox for setting FX channels * - * Copyright (c) 2008-2014 Tobias Doerffel + * Copyright (c) 2004-2014 Tobias Doerffel * * This file is part of LMMS - https://lmms.io * @@ -22,32 +22,32 @@ * */ -#ifndef _SPECTRUM_ANALYZER_CONTROL_DIALOG_H -#define _SPECTRUM_ANALYZER_CONTROL_DIALOG_H +#ifndef FX_LINE_LCD_SPIN_BOX_H +#define FX_LINE_LCD_SPIN_BOX_H -#include "EffectControlDialog.h" +#include "LcdSpinBox.h" + +class TrackView; -class SpectrumAnalyzerControls; - - -class SpectrumAnalyzerControlDialog : public EffectControlDialog +class FxLineLcdSpinBox : public LcdSpinBox { Q_OBJECT public: - SpectrumAnalyzerControlDialog( SpectrumAnalyzerControls* controls ); - virtual ~SpectrumAnalyzerControlDialog() - { - } + FxLineLcdSpinBox(int numDigits, QWidget * parent, const QString& name, TrackView * tv = NULL) : + LcdSpinBox(numDigits, parent, name), m_tv(tv) + {} + virtual ~FxLineLcdSpinBox() {} + + void setTrackView(TrackView * tv); + +protected: + void mouseDoubleClickEvent(QMouseEvent* event) override; + void contextMenuEvent(QContextMenuEvent* event) override; private: - virtual void paintEvent( QPaintEvent* event ); + TrackView * m_tv; - SpectrumAnalyzerControls* m_controls; - - QPixmap m_logXAxis; - QPixmap m_logYAxis; - -} ; +}; #endif diff --git a/include/FxMixer.h b/include/FxMixer.h index 053480a6a..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; }; @@ -121,7 +121,7 @@ class FxRoute : public QObject }; -class EXPORT FxMixer : public Model, public JournallingObject +class LMMS_EXPORT FxMixer : public Model, public JournallingObject { Q_OBJECT public: @@ -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 30c759838..a7662321a 100644 --- a/include/FxMixerView.h +++ b/include/FxMixerView.h @@ -41,7 +41,7 @@ class QButtonGroup; class FxLine; -class EXPORT FxMixerView : public QWidget, public ModelView, +class LMMS_EXPORT FxMixerView : public QWidget, public ModelView, public SerializingObjectHook { Q_OBJECT @@ -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 dc1d1fe16..2a6fc4f8a 100644 --- a/include/Graph.h +++ b/include/Graph.h @@ -38,19 +38,24 @@ class graphModel; -class EXPORT Graph : public QWidget, public ModelView +class LMMS_EXPORT Graph : public QWidget, public ModelView { Q_OBJECT public: enum graphStyle { - NearestStyle, - LinearStyle, - LinearNonCyclicStyle, - BarStyle, + NearestStyle, //!< draw as stairs + LinearStyle, //!< connect each 2 samples with a line, with wrapping + LinearNonCyclicStyle, //!< LinearStyle without wrapping + BarStyle, //!< draw thick bars NumGraphStyles }; + /** + * @brief Constructor + * @param _width Pixel width of widget + * @param _height Pixel height of widget + */ Graph( QWidget * _parent, graphStyle _style = Graph::LinearStyle, int _width = 132, int _height = 104 @@ -82,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 ); @@ -111,10 +116,24 @@ private: } ; -class EXPORT graphModel : public Model +/** + @brief 2 dimensional function plot + + Function plot graph with discrete x scale and continous y scale + This makes it possible to display "#x" samples +*/ +class LMMS_EXPORT graphModel : public Model { Q_OBJECT public: + /** + * @brief Constructor + * @param _min Minimum y value to display + * @param _max Maximum y value to display + * @param _size Number of samples (e.g. x value) + * @param _step Step size on y axis where values snap to, or 0.0f + * for "no snapping" + */ graphModel( float _min, float _max, int _size, @@ -146,14 +165,21 @@ public: return( m_samples.data() ); } - void convolve(const float *convolution, const int convolutionLength, const int centerOffset); + //! Make cyclic convolution + //! @param convolution Samples to convolve with + //! @param convolutionLength Number of samples to take for each sum + //! @param centerOffset Offset for resulting values + void convolve(const float *convolution, + const int convolutionLength, const int centerOffset); public slots: + //! Set range of y values void setRange( float _min, float _max ); void setLength( int _size ); - + //! Update one sample void setSampleAt( int x, float val ); + //! Update samples array void setSamples( const float * _value ); void setWaveToSine(); @@ -169,6 +195,7 @@ public slots: void invert(); void shiftPhase( int _deg ); void clear(); + void clearInvisible(); signals: void lengthChanged(); 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/GuiApplication.h b/include/GuiApplication.h index b429b591e..976d6abfc 100644 --- a/include/GuiApplication.h +++ b/include/GuiApplication.h @@ -27,7 +27,7 @@ #include -#include "export.h" +#include "lmms_export.h" class QLabel; @@ -41,7 +41,7 @@ class PianoRollWindow; class ProjectNotes; class SongEditorWindow; -class EXPORT GuiApplication : public QObject +class LMMS_EXPORT GuiApplication : public QObject { Q_OBJECT; public: diff --git a/include/ImportFilter.h b/include/ImportFilter.h index 304de5fa4..ccefd3db2 100644 --- a/include/ImportFilter.h +++ b/include/ImportFilter.h @@ -34,7 +34,7 @@ class TrackContainer; -class EXPORT ImportFilter : public Plugin +class LMMS_EXPORT ImportFilter : public Plugin { public: ImportFilter( const QString & _file_name, @@ -78,20 +78,26 @@ protected: return m_file.read( _data, _len ); } + inline QByteArray readAllData() + { + m_file.seek(0); + return m_file.readAll(); + } + inline void ungetChar( char _ch ) { 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 ec7245dce..438197cd8 100644 --- a/include/Instrument.h +++ b/include/Instrument.h @@ -27,7 +27,7 @@ #define INSTRUMENT_H #include -#include "export.h" +#include "lmms_export.h" #include "lmms_basics.h" #include "MemoryManager.h" #include "MidiTime.h" @@ -41,7 +41,7 @@ class NotePlayHandle; class Track; -class EXPORT Instrument : public Plugin +class LMMS_EXPORT Instrument : public Plugin { MM_OPERATORS public: @@ -55,14 +55,17 @@ public: Q_DECLARE_FLAGS(Flags, Flag); - Instrument( InstrumentTrack * _instrument_track, - const Descriptor * _descriptor ); + Instrument(InstrumentTrack * _instrument_track, + const Descriptor * _descriptor, + const Descriptor::SubPluginFeatures::Key * key = nullptr); virtual ~Instrument() = default; // -------------------------------------------------------------------- // functions that can/should be re-implemented: // -------------------------------------------------------------------- + virtual bool hasNoteInput() const { return true; } + // if the plugin doesn't play each note, it can create an instrument- // play-handle and re-implement this method, so that it mixes its // output buffer only once per mixer-period @@ -107,16 +110,18 @@ public: return true; } - virtual QString fullDisplayName() const; + QString fullDisplayName() const override; // -------------------------------------------------------------------- // provided functions: // -------------------------------------------------------------------- - // instantiate instrument-plugin with given name or return NULL - // on failure - static Instrument * instantiate( const QString & _plugin_name, - InstrumentTrack * _instrument_track ); + //! instantiate instrument-plugin with given name or return NULL + //! on failure + static Instrument * instantiate(const QString & _plugin_name, + InstrumentTrack * _instrument_track, + const Plugin::Descriptor::SubPluginFeatures::Key* key, + bool keyFromDnd = false); virtual bool isFromTrack( const Track * _track ) const; 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 11acb22c7..65fd1632d 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 f027b7d11..ac5fc3222 100644 --- a/include/InstrumentPlayHandle.h +++ b/include/InstrumentPlayHandle.h @@ -28,9 +28,9 @@ #include "PlayHandle.h" #include "Instrument.h" #include "NotePlayHandle.h" -#include "export.h" +#include "lmms_export.h" -class EXPORT InstrumentPlayHandle : public PlayHandle +class LMMS_EXPORT InstrumentPlayHandle : public PlayHandle { public: InstrumentPlayHandle( Instrument * instrument, InstrumentTrack* instrumentTrack ); @@ -40,16 +40,9 @@ public: } - virtual void play( sampleFrame * _working_buffer ) + void play( sampleFrame * _working_buffer ) override { - // if the instrument is midi-based, we can safely render right away - if( m_instrument->flags() & Instrument::IsMidiBased ) - { - m_instrument->play( _working_buffer ); - return; - } - - // if not, we need to ensure that all our nph's have been processed first + // ensure that all our nph's have been processed first ConstNotePlayHandleList nphv = NotePlayHandle::nphsOfInstrumentTrack( m_instrument->instrumentTrack(), true ); bool nphsLeft; @@ -72,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 d8e7330f4..546653a03 100644 --- a/include/InstrumentTrack.h +++ b/include/InstrumentTrack.h @@ -37,6 +37,7 @@ #include "Piano.h" #include "PianoView.h" #include "Pitch.h" +#include "Plugin.h" #include "Track.h" @@ -53,6 +54,7 @@ class InstrumentTrackWindow; class InstrumentMidiIOView; class InstrumentMiscView; class Knob; +class FxLineLcdSpinBox; class LcdSpinBox; class LeftRightNav; class midiPortMenu; @@ -64,7 +66,7 @@ class LedCheckBox; class QLabel; -class EXPORT InstrumentTrack : public Track, public MidiEventProcessor +class LMMS_EXPORT InstrumentTrack : public Track, public MidiEventProcessor { Q_OBJECT MM_OPERATORS @@ -79,8 +81,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 ); @@ -112,7 +114,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) @@ -132,24 +134,26 @@ 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; // load instrument whose name matches given one - Instrument * loadInstrument( const QString & _instrument_name ); + Instrument * loadInstrument(const QString & _instrument_name, + const Plugin::Descriptor::SubPluginFeatures::Key* key = nullptr, + bool keyFromDnd = false); AudioPort * audioPort() { @@ -222,10 +226,11 @@ signals: void midiNoteOff( const Note& ); void nameChanged(); void newNote(); + void endNote(); protected: - virtual QString nodeName() const + QString nodeName() const override { return "instrumenttrack"; } @@ -326,12 +331,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: @@ -413,8 +418,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: @@ -426,11 +431,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: @@ -439,8 +444,11 @@ 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 + void adjustTabSize(QWidget *w); InstrumentTrack * m_track; InstrumentTrackView * m_itv; @@ -454,7 +462,7 @@ private: QLabel * m_pitchLabel; LcdSpinBox* m_pitchRangeSpinBox; QLabel * m_pitchRangeLabel; - LcdSpinBox * m_effectChannelNumber; + FxLineLcdSpinBox * m_effectChannelNumber; diff --git a/include/InstrumentView.h b/include/InstrumentView.h index d4f835708..838ed2d91 100644 --- a/include/InstrumentView.h +++ b/include/InstrumentView.h @@ -32,11 +32,12 @@ class InstrumentTrackWindow; -class EXPORT InstrumentView : public PluginView +//! Instrument view with variable size +class LMMS_EXPORT InstrumentView : public PluginView { public: InstrumentView( Instrument * _instrument, QWidget * _parent ); - virtual ~InstrumentView(); + ~InstrumentView() override; Instrument * model() { @@ -48,11 +49,25 @@ public: return( castModel() ); } - virtual void setModel( Model * _model, bool = false ); + void setModel( Model * _model, bool = false ) override; InstrumentTrackWindow * instrumentTrackWindow(); } ; + + +//! Instrument view with fixed LMMS-default size +class LMMS_EXPORT InstrumentViewFixedSize : public InstrumentView +{ + QSize sizeHint() const override { return QSize(250, 250); } + QSize minimumSizeHint() const override { return sizeHint(); } + +public: + using InstrumentView::InstrumentView; + ~InstrumentViewFixedSize() override; +} ; + + #endif diff --git a/include/export.h b/include/IoHelper.h similarity index 50% rename from include/export.h rename to include/IoHelper.h index dd3709704..687e000d1 100644 --- a/include/export.h +++ b/include/IoHelper.h @@ -1,7 +1,7 @@ /* - * export.h - macros for export-declarations + * IoHelper.h - helper functions for file I/O * - * Copyright (c) 2008 Tobias Doerffel + * Copyright (c) 2018 Hyunjin Song * * This file is part of LMMS - https://lmms.io * @@ -22,25 +22,51 @@ * */ -#ifndef EXPORT_H -#define EXPORT_H #include "lmmsconfig.h" +#include + + +#ifdef _WIN32 +#include + +std::wstring toWString(const std::string& s) +{ + std::wstring ret; + int len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), + s.length(), nullptr, 0); + if (len == 0) + { + return ret; + } + ret.resize(len); + MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s.length(), &ret[0], len); + return ret; +} +#endif + #ifdef LMMS_BUILD_WIN32 - -#ifdef PLUGIN_NAME -#define EXPORT __declspec(dllimport) -#define PLUGIN_EXPORT __declspec(dllexport) +#include +#define F_OPEN_UTF8(a, b) _wfopen(toWString(a).data(), L##b) #else -#define EXPORT __declspec(dllexport) +#ifdef LMMS_HAVE_UNISTD_H +#include +#endif +#define F_OPEN_UTF8(a, b) fopen((a).data(), b) #endif +int fileToDescriptor(FILE* f, bool closeFile = true) +{ + int fh; + if (f == NULL) {return -1;} + +#ifdef LMMS_BUILD_WIN32 + fh = _dup(_fileno(f)); #else - -#define EXPORT -#define PLUGIN_EXPORT - + fh = dup(fileno(f)); #endif -#endif + if (closeFile) {fclose(f);} + return fh; +} diff --git a/include/JournallingObject.h b/include/JournallingObject.h index f8e1a5950..f4755994b 100644 --- a/include/JournallingObject.h +++ b/include/JournallingObject.h @@ -31,7 +31,7 @@ #include "SerializingObject.h" -class EXPORT JournallingObject : public SerializingObject +class LMMS_EXPORT JournallingObject : public SerializingObject { public: JournallingObject(); @@ -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 f6c9cfa99..4f8064731 100644 --- a/include/Knob.h +++ b/include/Knob.h @@ -30,7 +30,6 @@ #include #include "AutomatableModelView.h" -#include "templates.h" class QPixmap; @@ -43,7 +42,7 @@ enum knobTypes -class EXPORT Knob : public QWidget, public FloatModelView +class LMMS_EXPORT Knob : public QWidget, public FloatModelView { Q_OBJECT Q_ENUMS( knobTypes ) @@ -74,6 +73,7 @@ class EXPORT Knob : public QWidget, public FloatModelView public: Knob( knobTypes _knob_num, QWidget * _parent = NULL, const QString & _name = QString() ); Knob( QWidget * _parent = NULL, const QString & _name = QString() ); //!< default ctor + Knob( const Knob& other ) = delete; virtual ~Knob(); // TODO: remove @@ -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/Ladspa2LMMS.h b/include/Ladspa2LMMS.h index e5d35fbb1..28fa25b89 100644 --- a/include/Ladspa2LMMS.h +++ b/include/Ladspa2LMMS.h @@ -30,7 +30,9 @@ #include "LadspaManager.h" -class EXPORT Ladspa2LMMS : public LadspaManager +//! Class responsible for sorting found plugins (by LadspaManager) +//! into categories +class LMMS_EXPORT Ladspa2LMMS : public LadspaManager { public: diff --git a/include/LadspaControl.h b/include/LadspaControl.h index 1cd8a304e..34f6c9ae2 100644 --- a/include/LadspaControl.h +++ b/include/LadspaControl.h @@ -36,7 +36,7 @@ typedef struct PortDescription port_desc_t; -class EXPORT LadspaControl : public Model, public JournallingObject +class LMMS_EXPORT LadspaControl : public Model, public JournallingObject { Q_OBJECT public: @@ -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/LadspaControlView.h b/include/LadspaControlView.h index 34689af4e..d2d0ca44d 100644 --- a/include/LadspaControlView.h +++ b/include/LadspaControlView.h @@ -33,7 +33,7 @@ class LadspaControl; -class EXPORT LadspaControlView : public QWidget, public ModelView +class LMMS_EXPORT LadspaControlView : public QWidget, public ModelView { Q_OBJECT public: diff --git a/include/LadspaManager.h b/include/LadspaManager.h index 2338fbd4b..f9ac76eae 100644 --- a/include/LadspaManager.h +++ b/include/LadspaManager.h @@ -36,7 +36,7 @@ #include -#include "export.h" +#include "lmms_export.h" #include "lmms_basics.h" @@ -80,7 +80,7 @@ typedef struct ladspaManagerStorage } ladspaManagerDescription; -class EXPORT LadspaManager +class LMMS_EXPORT LadspaManager { public: diff --git a/include/LcdSpinBox.h b/include/LcdSpinBox.h index d6896f52b..379b743ac 100644 --- a/include/LcdSpinBox.h +++ b/include/LcdSpinBox.h @@ -30,17 +30,17 @@ #include "AutomatableModelView.h" -class EXPORT LcdSpinBox : public LcdWidget, public IntModelView +class LMMS_EXPORT LcdSpinBox : public LcdWidget, public IntModelView { Q_OBJECT public: - LcdSpinBox( int numDigits, QWidget* parent, const QString& name = QString::null ); + LcdSpinBox( int numDigits, QWidget* parent, const QString& name = QString() ); - LcdSpinBox( int numDigits, const QString& style, QWidget* parent, const QString& name = QString::null ); + LcdSpinBox( int numDigits, const QString& style, QWidget* parent, const QString& name = QString() ); 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 89bafd1d1..f4c7d1579 100644 --- a/include/LcdWidget.h +++ b/include/LcdWidget.h @@ -29,9 +29,9 @@ #include #include -#include "export.h" +#include "lmms_export.h" -class EXPORT LcdWidget : public QWidget +class LMMS_EXPORT LcdWidget : public QWidget { Q_OBJECT @@ -40,9 +40,9 @@ class EXPORT LcdWidget : public QWidget Q_PROPERTY( QColor textShadowColor READ textShadowColor WRITE setTextShadowColor ) public: - LcdWidget( QWidget* parent, const QString& name = QString::null ); - LcdWidget( int numDigits, QWidget* parent, const QString& name = QString::null ); - LcdWidget( int numDigits, const QString& style, QWidget* parent, const QString& name = QString::null ); + LcdWidget( QWidget* parent, const QString& name = QString() ); + LcdWidget( int numDigits, QWidget* parent, const QString& name = QString() ); + LcdWidget( int numDigits, const QString& style, QWidget* parent, const QString& name = QString() ); virtual ~LcdWidget(); @@ -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 b1c901ed6..66d7ce07e 100644 --- a/include/LedCheckbox.h +++ b/include/LedCheckbox.h @@ -32,7 +32,7 @@ class QPixmap; -class EXPORT LedCheckBox : public AutomatableButton +class LMMS_EXPORT LedCheckBox : public AutomatableButton { Q_OBJECT public: @@ -45,10 +45,10 @@ public: } ; LedCheckBox( const QString & _txt, QWidget * _parent, - const QString & _name = QString::null, + const QString & _name = QString(), LedColors _color = Yellow ); LedCheckBox( QWidget * _parent, - const QString & _name = QString::null, + const QString & _name = QString(), LedColors _color = Yellow ); virtual ~LedCheckBox(); @@ -64,7 +64,7 @@ public: Q_PROPERTY( QString text READ text WRITE setText ) protected: - virtual void paintEvent( QPaintEvent * _pe ); + void paintEvent( QPaintEvent * _pe ) override; private: diff --git a/include/LfoController.h b/include/LfoController.h index 9dfbba671..8fc35fd09 100644 --- a/include/LfoController.h +++ b/include/LfoController.h @@ -49,18 +49,18 @@ public: virtual ~LfoController(); - virtual void saveSettings( QDomDocument & _doc, QDomElement & _this ); - virtual void loadSettings( const QDomElement & _this ); - virtual QString nodeName() const; + void saveSettings( QDomDocument & _doc, QDomElement & _this ) override; + void loadSettings( const QDomElement & _this ) override; + QString nodeName() const override; public slots: - virtual ControllerDialog * createDialog( QWidget * _parent ); + ControllerDialog * createDialog( QWidget * _parent ) override; protected: // The internal per-controller value updating function - virtual void updateValueBuffer(); + void updateValueBuffer() override; FloatModel m_baseModel; TempoSyncKnobModel m_speedModel; @@ -98,8 +98,8 @@ public: protected: - virtual void contextMenuEvent( QContextMenuEvent * _me ); - virtual void modelChanged(); + void contextMenuEvent( QContextMenuEvent * _me ) override; + void modelChanged() override; LfoController * m_lfo; diff --git a/include/LmmsPalette.h b/include/LmmsPalette.h index 5016ee978..a8ee5d1c8 100644 --- a/include/LmmsPalette.h +++ b/include/LmmsPalette.h @@ -24,13 +24,13 @@ */ #include -#include "export.h" +#include "lmms_export.h" #ifndef LMMSPALETTE_H #define LMMSPALETTE_H -class EXPORT LmmsPalette : public QWidget +class LMMS_EXPORT LmmsPalette : public QWidget { Q_OBJECT Q_PROPERTY( QColor background READ background WRITE setBackground ) @@ -43,8 +43,6 @@ class EXPORT LmmsPalette : public QWidget Q_PROPERTY( QColor brightText READ brightText WRITE setBrightText ) Q_PROPERTY( QColor highlight READ highlight WRITE setHighlight ) Q_PROPERTY( QColor highlightedText READ highlightedText WRITE setHighlightedText ) - Q_PROPERTY( QColor toolTipText READ toolTipText WRITE setToolTipText ) - Q_PROPERTY( QColor toolTipBase READ toolTipBase WRITE setToolTipBase ) public: LmmsPalette( QWidget * parent, QStyle * stylearg ); @@ -65,8 +63,6 @@ public: ACCESSMET( brightText, setBrightText ) ACCESSMET( highlight, setHighlight ) ACCESSMET( highlightedText, setHighlightedText ) - ACCESSMET( toolTipText, setToolTipText ) - ACCESSMET( toolTipBase, setToolTipBase ) #undef ACCESSMET @@ -83,8 +79,6 @@ private: QColor m_brightText; QColor m_highlight; QColor m_highlightedText; - QColor m_toolTipText; - QColor m_toolTipBase; }; diff --git a/include/LmmsStyle.h b/include/LmmsStyle.h index 88b8a2112..ccf14396c 100644 --- a/include/LmmsStyle.h +++ b/include/LmmsStyle.h @@ -67,21 +67,21 @@ public: { } - virtual QPalette standardPalette( void ) const; + QPalette standardPalette( void ) const override; virtual void drawComplexControl( ComplexControl control, const QStyleOptionComplex * option, QPainter *painter, - const QWidget *widget ) const; + const QWidget *widget ) const override; virtual void drawPrimitive( PrimitiveElement element, const QStyleOption *option, QPainter *painter, - const QWidget *widget = 0 ) const; + const QWidget *widget = 0 ) const override; virtual int pixelMetric( PixelMetric metric, const QStyleOption * option = 0, - const QWidget * widget = 0 ) const; + const QWidget * widget = 0 ) const override; static QPalette * s_palette; diff --git a/include/LocaleHelper.h b/include/LocaleHelper.h new file mode 100644 index 000000000..c5d9d4c46 --- /dev/null +++ b/include/LocaleHelper.h @@ -0,0 +1,67 @@ +/* + * LocaleHelper.h - compatibility functions for handling decimal separators + * Providing helper functions which handle both periods and commas + * for decimal separators to load old projects correctly + * + * Copyright (c) 2014 Tobias Doerffel + * Copyright (c) 2018 Hyunjin Song + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef LOCALEHELPER_H +#define LOCALEHELPER_H + +#include + +#include +#include + +namespace LocaleHelper +{ +inline double toDouble(QString str, bool* ok = nullptr) +{ + bool isOkay; + double value; + QLocale c(QLocale::C); + c.setNumberOptions(QLocale::RejectGroupSeparator); + value = c.toDouble(str, &isOkay); + if (!isOkay) + { + QLocale german(QLocale::German); + german.setNumberOptions(QLocale::RejectGroupSeparator); + value = german.toDouble(str, &isOkay); + } + if (ok != nullptr) {*ok = isOkay;} + return value; +} + +inline float toFloat(QString str, bool* ok = nullptr) +{ + double d = toDouble(str, ok); + if (!std::isinf(d) && std::fabs(d) > std::numeric_limits::max()) + { + if (ok != nullptr) {*ok = false;} + return 0.0f; + } + return static_cast(d); +} +} + +#endif // LOCALEHELPER_H diff --git a/include/MainApplication.h b/include/MainApplication.h index d3acb95ca..d28900213 100644 --- a/include/MainApplication.h +++ b/include/MainApplication.h @@ -3,7 +3,7 @@ * * Copyright (c) 2017-2017 Tres Finocchiaro * - * This file is part of LMMS - http://lmms.io + * 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 @@ -31,12 +31,10 @@ #ifdef LMMS_BUILD_WIN32 #include -#if QT_VERSION >= 0x050000 #include #endif -#endif -#if defined(LMMS_BUILD_WIN32) && QT_VERSION >= 0x050000 +#if defined(LMMS_BUILD_WIN32) class MainApplication : public QApplication, public QAbstractNativeEventFilter #else class MainApplication : public QApplication @@ -44,13 +42,11 @@ 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); -#if QT_VERSION >= 0x050000 bool nativeEventFilter(const QByteArray& eventType, void* message, long* result); -#endif #endif inline QString& queuedFile() { diff --git a/include/MainWindow.h b/include/MainWindow.h index 0c6addcdb..5dc102321 100644 --- a/include/MainWindow.h +++ b/include/MainWindow.h @@ -61,7 +61,7 @@ public: void addSpacingToToolBar( int _size ); // wrap the widget with a window decoration and add it to the workspace - EXPORT SubWindow* addWindowedWidget(QWidget *w, Qt::WindowFlags windowFlags=0); + LMMS_EXPORT SubWindow* addWindowedWidget(QWidget *w, Qt::WindowFlags windowFlags=0); /// @@ -148,7 +148,6 @@ public slots: void emptySlot(); void createNewProject(); - void createNewProjectFromTemplate( QAction * _idx ); void openProject(); bool saveProject(); bool saveProjectAs(); @@ -177,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: @@ -204,10 +203,6 @@ private: QWidget * m_toolBar; QGridLayout * m_toolBarLayout; - QMenu * m_templatesMenu; - QMenu * m_recentlyOpenedProjectsMenu; - int m_custom_templates_count; - struct keyModifiers { keyModifiers() : @@ -240,10 +235,7 @@ private: private slots: void browseHelp(); - void fillTemplatesMenu(); - void openRecentlyOpenedProject( QAction * _action ); void showTool( QAction * _idx ); - void updateRecentlyOpenedProjectsMenu(); void updateViewMenu( void ); void updateConfig( QAction * _who ); void onToggleMetronome(); diff --git a/include/MemoryManager.h b/include/MemoryManager.h index 23561e4c0..4c225e026 100644 --- a/include/MemoryManager.h +++ b/include/MemoryManager.h @@ -30,9 +30,9 @@ #include #include -#include "export.h" +#include "lmms_export.h" -class EXPORT MemoryManager +class LMMS_EXPORT MemoryManager { public: struct ThreadGuard 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/MidiApple.h b/include/MidiApple.h index dcef23a83..21b88073b 100644 --- a/include/MidiApple.h +++ b/include/MidiApple.h @@ -47,7 +47,7 @@ public: inline static QString probeDevice() { - return QString::Null(); // no midi device name + return QString(); // no midi device name } inline static QString name() @@ -56,7 +56,7 @@ public: } inline static QString configSection() { - return QString::Null(); // no configuration settings + return QString(); // no configuration settings } virtual void processOutEvent( const MidiEvent & _me, 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 980afe288..f809d3c36 100644 --- a/include/MidiDummy.h +++ b/include/MidiDummy.h @@ -46,17 +46,17 @@ public: inline static QString probeDevice() { - return QString::Null(); // no midi device name + return QString(); // no midi device name } inline static QString configSection() { - return QString::Null(); // no configuration settings + return QString(); // no configuration settings } protected: - virtual void sendByte( const unsigned char ) + void sendByte( const unsigned char ) override { } diff --git a/include/MidiOss.h b/include/MidiOss.h index 27ebf0771..7e1f179ef 100644 --- a/include/MidiOss.h +++ b/include/MidiOss.h @@ -58,8 +58,8 @@ public: } protected: - virtual void sendByte( const unsigned char c ); - virtual void run(); + void sendByte( const unsigned char c ) override; + void run() override; private: diff --git a/include/MidiPort.h b/include/MidiPort.h index 07c61d788..e9cba39ed 100644 --- a/include/MidiPort.h +++ b/include/MidiPort.h @@ -103,10 +103,10 @@ public: void processOutEvent( const MidiEvent& event, const MidiTime& time = MidiTime() ); - virtual void saveSettings( QDomDocument& doc, QDomElement& thisElement ); - virtual void loadSettings( const QDomElement& thisElement ); + void saveSettings( QDomDocument& doc, QDomElement& thisElement ) override; + void loadSettings( const QDomElement& thisElement ) override; - virtual QString nodeName() const + QString nodeName() const override { return "midiport"; } diff --git a/include/MidiPortMenu.h b/include/MidiPortMenu.h index b963a7bd9..ce39c4aac 100644 --- a/include/MidiPortMenu.h +++ b/include/MidiPortMenu.h @@ -51,7 +51,7 @@ protected slots: private: - virtual void modelChanged(); + void modelChanged() override; MidiPort::Modes m_mode; diff --git a/include/MidiSndio.h b/include/MidiSndio.h index d115993fe..14ecfa0e9 100644 --- a/include/MidiSndio.h +++ b/include/MidiSndio.h @@ -59,8 +59,8 @@ public: protected: - virtual void sendByte(const unsigned char c); - virtual void run(void); + void sendByte(const unsigned char c) override; + void run(void) override; private: struct mio_hdl *m_hdl; diff --git a/include/MidiTime.h b/include/MidiTime.h index 37fcf6258..952b4b6d5 100644 --- a/include/MidiTime.h +++ b/include/MidiTime.h @@ -29,18 +29,18 @@ #include -#include "export.h" +#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; -class EXPORT TimeSig +class LMMS_EXPORT TimeSig { public: // in a time signature, @@ -57,22 +57,22 @@ private: }; -class EXPORT MidiTime +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 toNearestTact() const; - MidiTime toAbsoluteTact() const; + MidiTime quantize(float) 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,24 +90,23 @@ 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; } ; #endif - diff --git a/include/MidiWinMM.h b/include/MidiWinMM.h index 08e49c108..a51fa7ed6 100644 --- a/include/MidiWinMM.h +++ b/include/MidiWinMM.h @@ -47,7 +47,7 @@ public: inline static QString probeDevice() { - return QString::Null(); // no midi device name + return QString(); // no midi device name } @@ -58,7 +58,7 @@ public: inline static QString configSection() { - return QString::Null(); // no configuration settings + return QString(); // no configuration settings } diff --git a/include/MixHelpers.h b/include/MixHelpers.h index 7f919aba1..872319f82 100644 --- a/include/MixHelpers.h +++ b/include/MixHelpers.h @@ -33,6 +33,10 @@ namespace MixHelpers bool isSilent( const sampleFrame* src, int frames ); +bool useNaNHandler(); + +void setNaNHandler( bool use ); + bool sanitize( sampleFrame * src, int frames ); /*! \brief Add samples from src to dst */ diff --git a/include/Mixer.h b/include/Mixer.h index 499205892..32eeb8977 100644 --- a/include/Mixer.h +++ b/include/Mixer.h @@ -66,7 +66,7 @@ const Octaves BaseOctave = DefaultOctave; class MixerWorkerThread; -class EXPORT Mixer : public QObject +class LMMS_EXPORT Mixer : public QObject { Q_OBJECT public: @@ -171,10 +171,14 @@ public: return m_audioDevStartFailed; } - void setAudioDevice( AudioDevice * _dev ); + //! Set new audio device. Old device will be deleted, + //! unless it's stored using storeAudioDevice + void setAudioDevice( AudioDevice * _dev , bool startNow ); + //! See overloaded function void setAudioDevice( AudioDevice * _dev, const struct qualitySettings & _qs, - bool _needs_fifo ); + bool _needs_fifo, + bool startNow ); void storeAudioDevice(); void restoreAudioDevice(); inline AudioDevice * audioDev() @@ -273,7 +277,13 @@ public: } - void getPeakValues( sampleFrame * _ab, const f_cnt_t _frames, float & peakLeft, float & peakRight ) const; + struct StereoSample + { + StereoSample(sample_t _left, sample_t _right) : left(_left), right(_right) {} + sample_t left; + sample_t right; + }; + StereoSample getPeakValues(sampleFrame * _ab, const f_cnt_t _frames) const; bool criticalXRuns() const; @@ -305,9 +315,13 @@ public: inline bool isMetronomeActive() const { return m_metronomeActive; } inline void setMetronomeActive(bool value = true) { m_metronomeActive = value; } + //! Block until a change in model can be done (i.e. wait for audio thread) void requestChangeInModel(); void doneChangeInModel(); + static bool isAudioDevNameValid(QString name); + static bool isMidiDevNameValid(QString name); + signals: void qualitySettingsChanged(); @@ -331,7 +345,7 @@ private: fifo * m_fifo; volatile bool m_writing; - virtual void run(); + void run() override; void write( surroundSampleFrame * buffer ); @@ -353,6 +367,8 @@ private: void clearInternal(); + //! Called by the audio thread to give control to other threads, + //! such that they can do changes in the model (like e.g. removing effects) void runChangesInModel(); bool m_renderOnly; @@ -392,6 +408,7 @@ private: bool m_isProcessing; // audio device stuff + void doSetAudioDevice( AudioDevice *_dev ); AudioDevice * m_audioDev; AudioDevice * m_oldAudioDev; QString m_audioDevName; 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/Model.h b/include/Model.h index 55e735a05..b40c21029 100644 --- a/include/Model.h +++ b/include/Model.h @@ -28,14 +28,14 @@ #include #include -#include "export.h" +#include "lmms_export.h" -class EXPORT Model : public QObject +class LMMS_EXPORT Model : public QObject { Q_OBJECT public: - Model( Model * _parent, QString _display_name = QString::null, + Model( Model * _parent, QString _display_name = QString(), bool _default_constructed = false ) : QObject( _parent ), m_displayName( _display_name ), diff --git a/include/ModelView.h b/include/ModelView.h index a1071ddc2..907cd14ef 100644 --- a/include/ModelView.h +++ b/include/ModelView.h @@ -29,7 +29,7 @@ #include "Model.h" -class EXPORT ModelView +class LMMS_EXPORT ModelView { public: ModelView( Model* model, QWidget* widget ); diff --git a/include/ModelVisitor.h b/include/ModelVisitor.h new file mode 100644 index 000000000..f9d156e30 --- /dev/null +++ b/include/ModelVisitor.h @@ -0,0 +1,64 @@ +/* + * ModelVisitor.h - visitors for automatable models + * + * Copyright (c) 2019-2019 Johannes Lorenz + * + * 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 MODELVISITOR_H +#define MODELVISITOR_H + +class AutomatableModel; +class BoolModel; +class IntModel; +class FloatModel; +class ComboBoxModel; +class TempoSyncKnobModel; + +class ModelVisitor +{ + template + void up(ModelType& m) { visit(static_cast(m)); } +public: + virtual void visit(AutomatableModel& ) {} + virtual void visit(BoolModel& m); + virtual void visit(IntModel& m); + virtual void visit(FloatModel& m); + virtual void visit(ComboBoxModel& m); + virtual void visit(TempoSyncKnobModel& m); + virtual ~ModelVisitor(); +}; + +class ConstModelVisitor +{ + template + void up(const ModelType& m) { + visit(static_cast(m)); } +public: + virtual void visit(const AutomatableModel& ) {} + virtual void visit(const BoolModel& m); + virtual void visit(const IntModel& m); + virtual void visit(const FloatModel& m); + virtual void visit(const ComboBoxModel& m); + virtual void visit(const TempoSyncKnobModel& m); + virtual ~ConstModelVisitor(); +}; + +#endif // MODELVISITOR_H 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 c14f9d931..30969b4c8 100644 --- a/include/Note.h +++ b/include/Note.h @@ -78,7 +78,7 @@ const float MaxDetuning = 4 * 12.0f; -class EXPORT Note : public SerializingObject +class LMMS_EXPORT Note : public SerializingObject { public: Note( const MidiTime & length = MidiTime( 0 ), @@ -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 f4b6c9ec4..3dba0f277 100644 --- a/include/NotePlayHandle.h +++ b/include/NotePlayHandle.h @@ -42,7 +42,7 @@ typedef QList NotePlayHandleList; typedef QList ConstNotePlayHandleList; -class EXPORT NotePlayHandle : public PlayHandle, public Note +class LMMS_EXPORT NotePlayHandle : public PlayHandle, public Note { MM_OPERATORS public: @@ -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 ); @@ -303,6 +303,7 @@ private: NotePlayHandleList m_subNotes; // used for chords and arpeggios volatile bool m_released; // indicates whether note is released bool m_releaseStarted; + bool m_hasMidiNote; bool m_hasParent; // indicates whether note has parent NotePlayHandle * m_parent; // parent note bool m_hadChildren; diff --git a/include/Oscillator.h b/include/Oscillator.h index 6e89f9cb1..408e69dbc 100644 --- a/include/Oscillator.h +++ b/include/Oscillator.h @@ -39,7 +39,7 @@ class IntModel; -class EXPORT Oscillator +class LMMS_EXPORT Oscillator { MM_OPERATORS public: diff --git a/include/Pattern.h b/include/Pattern.h index 5924a0862..5192da9fa 100644 --- a/include/Pattern.h +++ b/include/Pattern.h @@ -46,7 +46,7 @@ class SampleBuffer; -class EXPORT Pattern : public TrackContentObject +class LMMS_EXPORT Pattern : public TrackContentObject { Q_OBJECT public: @@ -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,22 +182,23 @@ public: void setMutedNoteBorderColor(QColor const & color) { m_mutedNoteBorderColor = color; } public slots: - virtual void update(); + void update() override; protected slots: void openInPianoRoll(); + void setGhostInPianoRoll(); void resetName(); void changeName(); 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 39d7fded9..74a3aab59 100644 --- a/include/PeakController.h +++ b/include/PeakController.h @@ -36,7 +36,7 @@ class PeakControllerEffect; typedef QVector PeakControllerEffectVector; -class EXPORT PeakController : public Controller +class LMMS_EXPORT PeakController : public Controller { Q_OBJECT public: @@ -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 9167804ae..27a15149e 100644 --- a/include/PianoRoll.h +++ b/include/PianoRoll.h @@ -38,13 +38,14 @@ #include "lmms_basics.h" #include "Song.h" #include "ToolTip.h" +#include "StepRecorder.h" +#include "StepRecorderWidget.h" class QPainter; class QPixmap; class QScrollBar; class QString; class QMenu; -class QSignalMapper; class ComboBox; class NotePlayHandle; @@ -59,6 +60,9 @@ class PianoRoll : public QWidget Q_PROPERTY( QColor lineColor READ lineColor WRITE setLineColor ) Q_PROPERTY( QColor noteModeColor READ noteModeColor WRITE setNoteModeColor ) Q_PROPERTY( QColor noteColor READ noteColor WRITE setNoteColor ) + Q_PROPERTY( QColor ghostNoteColor READ ghostNoteColor WRITE setGhostNoteColor ) + Q_PROPERTY( QColor noteTextColor READ noteTextColor WRITE setNoteTextColor ) + Q_PROPERTY( QColor ghostNoteTextColor READ ghostNoteTextColor WRITE setGhostNoteTextColor ) Q_PROPERTY( QColor barColor READ barColor WRITE setBarColor ) Q_PROPERTY( QColor selectedNoteColor READ selectedNoteColor WRITE setSelectedNoteColor ) Q_PROPERTY( QColor textColor READ textColor WRITE setTextColor ) @@ -67,6 +71,8 @@ class PianoRoll : public QWidget Q_PROPERTY( QColor markedSemitoneColor READ markedSemitoneColor WRITE setMarkedSemitoneColor ) Q_PROPERTY( int noteOpacity READ noteOpacity WRITE setNoteOpacity ) Q_PROPERTY( bool noteBorders READ noteBorders WRITE setNoteBorders ) + Q_PROPERTY( int ghostNoteOpacity READ ghostNoteOpacity WRITE setGhostNoteOpacity ) + Q_PROPERTY( bool ghostNoteBorders READ ghostNoteBorders WRITE setGhostNoteBorders ) Q_PROPERTY( QColor backgroundShade READ backgroundShade WRITE setBackgroundShade ) public: enum EditModes @@ -86,6 +92,9 @@ public: void showPanTextFloat(panning_t pan, const QPoint &pos, int timeout=-1); void setCurrentPattern( Pattern* newPattern ); + void setGhostPattern( Pattern* newPattern ); + void loadGhostNotes( const QDomElement & de ); + void loadMarkedSemiTones(const QDomElement & de); inline void stopRecording() { @@ -97,6 +106,11 @@ public: return m_recording; } + inline bool isStepRecording() const + { + return m_stepRecorder.isRecording(); + } + const Pattern* currentPattern() const { return m_pattern; @@ -122,6 +136,8 @@ public: void setNoteModeColor( const QColor & c ); QColor noteColor() const; void setNoteColor( const QColor & c ); + QColor noteTextColor() const; + void setNoteTextColor( const QColor & c ); QColor barColor() const; void setBarColor( const QColor & c ); QColor selectedNoteColor() const; @@ -138,27 +154,35 @@ public: void setNoteOpacity( const int i ); bool noteBorders() const; void setNoteBorders( const bool b ); + QColor ghostNoteColor() const; + void setGhostNoteColor( const QColor & c ); + QColor ghostNoteTextColor() const; + void setGhostNoteTextColor( const QColor & c ); + int ghostNoteOpacity() const; + void setGhostNoteOpacity( const int i ); + bool ghostNoteBorders() const; + void setGhostNoteBorders( const bool b ); QColor backgroundShade() const; void setBackgroundShade( const QColor & c ); 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, - int width, const Note * n, const QColor & noteCol, - const QColor & selCol, const int noteOpc, const bool borderless ); + int width, const Note * n, const QColor & noteCol, const QColor & noteTextColor, + const QColor & selCol, const int noteOpc, const bool borderless, bool drawNoteName ); void removeSelection(); void selectAll(); NoteVector getSelectedNotes(); @@ -172,6 +196,7 @@ protected slots: void play(); void record(); void recordAccompany(); + bool toggleStepRecording(); void stop(); void startRecordNote( const Note & n ); @@ -189,9 +214,11 @@ protected slots: void updatePosition(const MidiTime & t ); void updatePositionAccompany(const MidiTime & t ); + void updatePositionStepRecording(const MidiTime & t ); void zoomingChanged(); void quantizeChanged(); + void noteLengthChanged(); void quantizeNotes(); void updateSemiToneMarkerMenu(); @@ -203,9 +230,12 @@ protected slots: void selectRegionFromPixels( int xStart, int xEnd ); + void clearGhostPattern(); + signals: void currentPatternChanged(); + void ghostPatternSet(bool); void semiToneMarkerMenuScaleSetEnabled(bool); void semiToneMarkerMenuChordSetEnabled(bool); @@ -266,6 +296,8 @@ private: void testPlayNote( Note * n ); void testPlayKey( int _key, int _vol, int _pan ); void pauseTestNotes(bool pause = true ); + void playChordNotes(int key, int velocity=-1); + void pauseChordNotes(int key); QList getAllOctavesForKey( int keyToMirror ) const; @@ -306,6 +338,13 @@ private: static const QVector m_zoomLevels; Pattern* m_pattern; + NoteVector m_ghostNotes; + + inline const NoteVector & ghostNotes() const + { + return m_ghostNotes; + } + QScrollBar * m_leftRightScroll; QScrollBar * m_topBottomScroll; @@ -343,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 @@ -378,12 +417,18 @@ private: friend class PianoRollWindow; + StepRecorderWidget m_stepRecorderWidget; + StepRecorder m_stepRecorder; + // qproperty fields QColor m_barLineColor; QColor m_beatLineColor; QColor m_lineColor; QColor m_noteModeColor; QColor m_noteColor; + QColor m_noteTextColor; + QColor m_ghostNoteColor; + QColor m_ghostNoteTextColor; QColor m_barColor; QColor m_selectedNoteColor; QColor m_textColor; @@ -391,7 +436,9 @@ private: QColor m_textShadow; QColor m_markedSemitoneColor; int m_noteOpacity; + int m_ghostNoteOpacity; bool m_noteBorders; + bool m_ghostNoteBorders; QColor m_backgroundShade; signals: @@ -408,14 +455,16 @@ public: PianoRollWindow(); const Pattern* currentPattern() const; - void setCurrentPattern(Pattern* pattern); + void setCurrentPattern( Pattern* pattern ); + void setGhostPattern( Pattern* pattern ); int quantization() const; - void play(); - void stop(); - void record(); - void recordAccompany(); + void play() override; + void stop() override; + void record() override; + void recordAccompany() override; + void toggleStepRecording() override; void stopRecording(); bool isRecording() const; @@ -425,25 +474,29 @@ 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(); private slots: - void patternRenamed(); + void updateAfterPatternChange(); + void ghostPatternSet( bool state ); private: - void focusInEvent(QFocusEvent * event); + void patternRenamed(); + void focusInEvent(QFocusEvent * event) override; + void stopStepRecording(); + void updateStepRecordingIcon(); PianoRoll* m_editor; @@ -452,6 +505,7 @@ private: ComboBox * m_noteLenComboBox; ComboBox * m_scaleComboBox; ComboBox * m_chordComboBox; + QPushButton * m_clearGhostButton; }; diff --git a/include/PianoView.h b/include/PianoView.h index 2a362c584..b793ee768 100644 --- a/include/PianoView.h +++ b/include/PianoView.h @@ -44,19 +44,19 @@ public: public: - virtual void keyPressEvent( QKeyEvent * ke ); - virtual void keyReleaseEvent( QKeyEvent * ke ); + void keyPressEvent( QKeyEvent * ke ) override; + void keyReleaseEvent( QKeyEvent * ke ) override; protected: - virtual void modelChanged(); - virtual void contextMenuEvent( QContextMenuEvent * _me ); - virtual void paintEvent( QPaintEvent * ); - virtual void mousePressEvent( QMouseEvent * me ); - virtual void mouseReleaseEvent( QMouseEvent * me ); - virtual void mouseMoveEvent( QMouseEvent * me ); - virtual void focusOutEvent( QFocusEvent * _fe ); - virtual void resizeEvent( QResizeEvent * _event ); + void modelChanged() override; + void contextMenuEvent( QContextMenuEvent * _me ) override; + void paintEvent( QPaintEvent * ) override; + void mousePressEvent( QMouseEvent * me ) override; + void mouseReleaseEvent( QMouseEvent * me ) override; + void mouseMoveEvent( QMouseEvent * me ) override; + void focusOutEvent( QFocusEvent * _fe ) override; + void resizeEvent( QResizeEvent * _event ) override; private: diff --git a/include/Pitch.h b/include/Pitch.h index 5ef1c3d62..2f866a1c5 100644 --- a/include/Pitch.h +++ b/include/Pitch.h @@ -25,8 +25,7 @@ #ifndef PITCH_H #define PITCH_H -#include "lmms_basics.h" -#include "Midi.h" +#include typedef int16_t pitch_t; diff --git a/include/PixmapButton.h b/include/PixmapButton.h index 9f6ef8071..e2fb58885 100644 --- a/include/PixmapButton.h +++ b/include/PixmapButton.h @@ -31,28 +31,28 @@ #include "AutomatableButton.h" -class EXPORT PixmapButton : public AutomatableButton +class LMMS_EXPORT PixmapButton : public AutomatableButton { Q_OBJECT public: PixmapButton( QWidget * _parent, - const QString & _name = QString::null ); + const QString & _name = QString() ); virtual ~PixmapButton(); 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 a1c8e5c33..1ddd632d1 100644 --- a/include/PlayHandle.h +++ b/include/PlayHandle.h @@ -28,7 +28,7 @@ #include #include -#include "export.h" +#include "lmms_export.h" #include "MemoryManager.h" @@ -40,7 +40,7 @@ class QThread; class Track; class AudioPort; -class EXPORT PlayHandle : public ThreadableJob +class LMMS_EXPORT PlayHandle : public ThreadableJob { public: enum Types @@ -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 793997635..cb8995bf2 100644 --- a/include/Plugin.h +++ b/include/Plugin.h @@ -40,8 +40,28 @@ class PixmapLoader; class PluginView; class AutomatableModel; +/** + Abstract representation of a plugin -class EXPORT Plugin : public Model, public JournallingObject + Such a plugin can be an Instrument, Effect, Tool plugin etc. + + Plugins have descriptors, containing meta info, which is used especially + by PluginFactory and friends. + + There are also Plugin keys (class Key, confusingly under + SubPluginFeatures), which contain pointers to the plugin descriptor. + + Some plugins have sub plugins, e.g. there is one CALF Plugin and for + each CALF effect, there is a CALF sub plugin. For those plugins, there + are keys for each sub plugin. These keys also link to the superior + Plugin::Descriptor. Additionally, they contain attributes that help the + superior Plugin saving them and recognizing them when loading. + + In case of sub plugins, the Descriptor has SubPluginFeatures. Those + are a bit like values to the sub plugins' keys (in terms of a key-value- + map). +*/ +class LMMS_EXPORT Plugin : public Model, public JournallingObject { MM_OPERATORS Q_OBJECT @@ -59,9 +79,9 @@ public: Undefined = 255 } ; - // descriptor holds information about a plugin - every external plugin - // has to instantiate such a descriptor in an extern "C"-section so that - // the plugin-loader is able to access information about the plugin + //! Descriptor holds information about a plugin - every external plugin + //! has to instantiate such a Descriptor in an extern "C"-section so that + //! the plugin-loader is able to access information about the plugin struct Descriptor { const char * name; @@ -71,23 +91,49 @@ public: int version; PluginTypes type; const PixmapLoader * logo; - const char * supportedFileTypes; + const char * supportedFileTypes; //!< csv list of extensions inline bool supportsFileType( const QString& extension ) const { return QString( supportedFileTypes ).split( QChar( ',' ) ).contains( extension ); } - class EXPORT SubPluginFeatures + /** + Access to non-key-data of a sub plugin + + If you consider sub plugin keys as keys in a + key-value-map, this is the lookup for the corresponding + values. In order to have flexibility between different + plugin APIs, this is rather an array of fixed data, + but a bunch of virtual functions taking the key and + returning some values (or modifying objects of other + classes). + */ + class LMMS_EXPORT SubPluginFeatures { public: + /** + Key reference a Plugin::Descriptor, and, + if the plugin has sub plugins, also reference + its sub plugin (using the attributes). + When keys are saved, those attributes are + written to XML in order to find the right sub + plugin when realoading. + + @note Any data that is not required to reference + the right Plugin or sub plugin should + not be here (but rather in + SubPluginFeatures, which are like values + in a key-value map). + */ struct Key { typedef QMap AttributeMap; inline Key( const Plugin::Descriptor * desc = NULL, - const QString & name = QString(), - const AttributeMap & am = AttributeMap() ) + const QString & name = QString(), + const AttributeMap & am = AttributeMap() + ) : desc( desc ), name( name ), @@ -101,12 +147,28 @@ public: inline bool isValid() const { - return desc != NULL && name.isNull() == false; + return desc != nullptr; } + //! Key to subplugin: reference to parent descriptor + //! Key to plugin: reference to its descriptor const Plugin::Descriptor* desc; + //! Descriptive name like "Calf Phaser". + //! Not required for key lookup and not saved + //! only used sometimes to temporary store descriptive names + //! @todo This is a bug, there should be a function + //! in SubPluginFeatures (to get the name) instead QString name; + //! Attributes that make up the key and identify + //! the sub plugin. They are being loaded and saved AttributeMap attributes; + + // helper functions to retrieve data that is + // not part of the key, but mapped via desc->subPluginFeatures + QString additionalFileExtensions() const; + QString displayName() const; + QString description() const; + const PixmapLoader* logo() const; } ; typedef QList KeyList; @@ -125,11 +187,40 @@ public: { } + //! While PluginFactory only collects the plugins, + //! this function is used by widgets like EffectSelectDialog + //! to find all possible sub plugins virtual void listSubPluginKeys( const Plugin::Descriptor *, KeyList & ) const { } + private: + // You can add values mapped by "Key" below + // The defaults are sane, i.e. redirect to sub plugin's + // supererior descriptor + + virtual QString additionalFileExtensions(const Key&) const + { + return QString(); + } + + virtual QString displayName(const Key& k) const + { + return k.isValid() ? k.name : QString(); + } + + virtual QString description(const Key& k) const + { + return k.isValid() ? k.desc->description : QString(); + } + + virtual const PixmapLoader* logo(const Key& k) const + { + Q_ASSERT(k.desc); + return k.desc->logo; + } + protected: const Plugin::PluginTypes m_type; } ; @@ -140,48 +231,66 @@ public: // typedef a list so we can easily work with list of plugin descriptors typedef QList DescriptorList; - // contructor of a plugin - Plugin( const Descriptor * descriptor, Model * parent ); + //! Constructor of a plugin + //! @param key Sub plugins must pass a key here, optional otherwise. + //! See the key() function + Plugin(const Descriptor * descriptor, Model * parent, + const Descriptor::SubPluginFeatures::Key *key = nullptr); virtual ~Plugin(); - // returns display-name out of descriptor - virtual QString displayName() const - { - return Model::displayName().isEmpty() - ? m_descriptor->displayName - : Model::displayName(); - } + //! Return display-name out of sub plugin or descriptor + QString displayName() const override; - // return plugin-type + //! Return logo out of sub plugin or descriptor + const PixmapLoader *logo() const; + + //! Return plugin type inline PluginTypes type( void ) const { return m_descriptor->type; } - // return plugin-descriptor for further information + //! Return plugin Descriptor inline const Descriptor * descriptor() const { return m_descriptor; } - // can be called if a file matching supportedFileTypes should be - // loaded/processed with the help of this plugin + //! Return the key referencing this plugin. If the Plugin has no + //! sub plugin features, the key is pretty useless. If it has, + //! this key will also contain the sub plugin attributes, and will be + //! a key to those SubPluginFeatures. + inline const Descriptor::SubPluginFeatures::Key & key() const + { + return m_key; + } + + //! Can be called if a file matching supportedFileTypes should be + //! loaded/processed with the help of this plugin virtual void loadFile( const QString & file ); - // Called if external source needs to change something but we cannot - // reference the class header. Should return null if not key not found. + //! Called if external source needs to change something but we cannot + //! reference the class header. Should return null if not key not found. virtual AutomatableModel* childModel( const QString & modelName ); - // returns an instance of a plugin whose name matches to given one - // if specified plugin couldn't be loaded, it creates a dummy-plugin - static Plugin * instantiate( const QString& pluginName, Model * parent, void * data ); + //! Overload if the argument passed to the plugin is a subPluginKey + //! If you can not pass the key and are aware that it's stored in + //! Engine::pickDndPluginKey(), use this function, too + static Plugin * instantiateWithKey(const QString& pluginName, Model * parent, + const Descriptor::SubPluginFeatures::Key *key, + bool keyFromDnd = false); - // create a view for the model + //! Return an instance of a plugin whose name matches to given one + //! if specified plugin couldn't be loaded, it creates a dummy-plugin + //! @param data Anything the plugin expects. If this is a pointer to a sub plugin key, + //! use instantiateWithKey instead + static Plugin * instantiate(const QString& pluginName, Model * parent, void *data); + + //! Create a view for the model PluginView * createView( QWidget * parent ); - protected: - // create a view for the model + //! Create a view for the model virtual PluginView* instantiateView( QWidget * ) = 0; void collectErrorForUI( QString errMsg ); @@ -189,6 +298,8 @@ protected: private: const Descriptor * m_descriptor; + Descriptor::SubPluginFeatures::Key m_key; + // pointer to instantiation-function in plugin typedef Plugin * ( * InstantiationHook )( Model * , void * ); diff --git a/include/PluginBrowser.h b/include/PluginBrowser.h index 75c7cd291..3cc54c6e4 100644 --- a/include/PluginBrowser.h +++ b/include/PluginBrowser.h @@ -31,6 +31,10 @@ #include "SideBarWidget.h" #include "Plugin.h" +class QLineEdit; +class QTreeWidget; +class QTreeWidgetItem; + class PluginBrowser : public SideBarWidget { @@ -39,18 +43,18 @@ public: PluginBrowser( QWidget * _parent ); virtual ~PluginBrowser() = default; +private slots: + void onFilterChanged( const QString & filter ); + private: + void addPlugins(); + void updateRootVisibility( int index ); + void updateRootVisibilities(); + QWidget * m_view; -}; - - - - -class PluginDescList : public QWidget -{ - Q_OBJECT -public: - PluginDescList(QWidget* parent); + QTreeWidget * m_descTree; + QTreeWidgetItem * m_lmmsRoot; + QTreeWidgetItem * m_lv2Root; }; @@ -60,7 +64,9 @@ class PluginDescWidget : public QWidget { Q_OBJECT public: - PluginDescWidget( const Plugin::Descriptor & _pd, QWidget * _parent ); + typedef Plugin::Descriptor::SubPluginFeatures::Key PluginKey; + PluginDescWidget( const PluginKey & _pk, QWidget * _parent ); + QString name() const; protected: @@ -72,7 +78,7 @@ protected: private: constexpr static int DEFAULT_HEIGHT{24}; - const Plugin::Descriptor & m_pluginDescriptor; + PluginKey m_pluginKey; QPixmap m_logo; bool m_mouseOver; diff --git a/include/PluginFactory.h b/include/PluginFactory.h index fb3e8ea94..17b178108 100644 --- a/include/PluginFactory.h +++ b/include/PluginFactory.h @@ -26,27 +26,28 @@ #define PLUGINFACTORY_H #include +#include #include #include #include +#include +#include -#include "export.h" +#include "lmms_export.h" #include "Plugin.h" class QLibrary; -class EXPORT PluginFactory +class LMMS_EXPORT PluginFactory { public: struct PluginInfo { - PluginInfo() : library(nullptr), descriptor(nullptr) {} - const QString name() const; QFileInfo file; - std::shared_ptr library; - Plugin::Descriptor* descriptor; + std::shared_ptr library = nullptr; + Plugin::Descriptor* descriptor = nullptr; bool isNull() const {return ! library;} }; @@ -56,6 +57,8 @@ public: PluginFactory(); ~PluginFactory(); + static void setupSearchPaths(); + /// Returns the singleton instance of PluginFactory. You won't need to call /// this directly, use pluginFactory instead. static PluginFactory* instance(); @@ -64,10 +67,17 @@ public: const Plugin::DescriptorList descriptors() const; const Plugin::DescriptorList descriptors(Plugin::PluginTypes type) const; + struct PluginInfoAndKey + { + PluginInfo info; + Plugin::Descriptor::SubPluginFeatures::Key key; + bool isNull() const { return info.isNull(); } + }; + /// Returns a list of all found plugins' PluginFactory::PluginInfo objects. const PluginInfoList& pluginInfos() const; /// Returns a plugin that support the given file extension - const PluginInfo pluginSupportingExtension(const QString& ext); + const PluginInfoAndKey pluginSupportingExtension(const QString& ext); /// Returns the PluginInfo object of the plugin with the given name. /// If the plugin is not found, an empty PluginInfo is returned (use @@ -84,7 +94,9 @@ public slots: private: DescriptorMap m_descriptors; PluginInfoList m_pluginInfos; - QMap m_pluginByExt; + + QMap m_pluginByExt; + QVector m_garbage; //!< cleaned up at destruction QHash m_errors; diff --git a/include/PluginIssue.h b/include/PluginIssue.h new file mode 100644 index 000000000..c00945805 --- /dev/null +++ b/include/PluginIssue.h @@ -0,0 +1,66 @@ +/* + * PluginIssue.h - PluginIssue class + * + * Copyright (c) 2019 Johannes Lorenz + * + * 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 PLUGINISSUE_H +#define PLUGINISSUE_H + +#include +#include + +//! Types of issues that can cause LMMS to not load a plugin +//! LMMS Plugins should use this to indicate errors +enum PluginIssueType +{ + unknownPortFlow, + unknownPortType, + tooManyInputChannels, + tooManyOutputChannels, + noOutputChannel, + portHasNoDef, + portHasNoMin, + portHasNoMax, + featureNotSupported, //!< plugin requires functionality LMMS can't offer + badPortType, //!< port type not supported + noIssue +}; + +//! Issue type bundled with informational string +class PluginIssue +{ + static const char* msgFor(const PluginIssueType& it); + + PluginIssueType m_issueType; + std::string m_info; + +public: + PluginIssue(PluginIssueType it, std::string msg = std::string()) + : m_issueType(it), m_info(msg) + { + } + friend QDebug operator<<(QDebug stream, const PluginIssue& iss); +}; + +QDebug operator<<(QDebug stream, const PluginIssue& iss); + +#endif // PLUGINISSUE_H diff --git a/include/PluginView.h b/include/PluginView.h index 414e2bcae..476d65acf 100644 --- a/include/PluginView.h +++ b/include/PluginView.h @@ -31,7 +31,7 @@ #include "ModelView.h" -class EXPORT PluginView : public QWidget, public ModelView +class LMMS_EXPORT PluginView : public QWidget, public ModelView { public: PluginView( Plugin * _plugin, QWidget * _parent ) : diff --git a/include/PresetPreviewPlayHandle.h b/include/PresetPreviewPlayHandle.h index 313c20897..a95b680ab 100644 --- a/include/PresetPreviewPlayHandle.h +++ b/include/PresetPreviewPlayHandle.h @@ -32,21 +32,21 @@ class InstrumentTrack; class PreviewTrackContainer; -class EXPORT PresetPreviewPlayHandle : public PlayHandle +class LMMS_EXPORT PresetPreviewPlayHandle : public PlayHandle { 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/ProjectJournal.h b/include/ProjectJournal.h index a89c9725a..cb487617b 100644 --- a/include/ProjectJournal.h +++ b/include/ProjectJournal.h @@ -34,6 +34,7 @@ class JournallingObject; +//! @warning many parts of this class may be rewritten soon class ProjectJournal { public: @@ -76,7 +77,10 @@ public: reallocID( _id, NULL ); } + //! hack, not used when saving a file static jo_id_t idToSave( jo_id_t id ); + //! hack, not used when loading a savefile + static jo_id_t idFromSave( jo_id_t id ); void clearJournal(); void stopAllJournalling(); diff --git a/include/ProjectNotes.h b/include/ProjectNotes.h index 4477b112f..fc97a8844 100644 --- a/include/ProjectNotes.h +++ b/include/ProjectNotes.h @@ -37,7 +37,7 @@ class QTextCharFormat; class QTextEdit; -class EXPORT ProjectNotes : public QMainWindow, public SerializingObject +class LMMS_EXPORT ProjectNotes : public QMainWindow, public SerializingObject { Q_OBJECT public: @@ -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 acc512063..1af9d422d 100644 --- a/include/ProjectRenderer.h +++ b/include/ProjectRenderer.h @@ -30,8 +30,9 @@ #include "Mixer.h" #include "OutputSettings.h" +#include "lmms_export.h" -class ProjectRenderer : public QThread +class LMMS_EXPORT ProjectRenderer : public QThread { Q_OBJECT public: @@ -85,7 +86,7 @@ signals: private: - virtual void run(); + void run() override; AudioFileDevice * m_fileDev; Mixer::qualitySettings m_qualitySettings; diff --git a/include/RecentProjectsMenu.h b/include/RecentProjectsMenu.h new file mode 100644 index 000000000..b3837ee2e --- /dev/null +++ b/include/RecentProjectsMenu.h @@ -0,0 +1,17 @@ +#ifndef RECENTPROJECTSMENU_H +#define RECENTPROJECTSMENU_H + +#include + +class RecentProjectsMenu : public QMenu +{ + Q_OBJECT +public: + RecentProjectsMenu(QWidget *parent = nullptr); + +private slots: + void fillMenu(); + void openProject(QAction * _action ); +}; + +#endif // RECENTPROJECTSMENU_H diff --git a/include/RemotePlugin.h b/include/RemotePlugin.h index e0df85003..862370d1f 100644 --- a/include/RemotePlugin.h +++ b/include/RemotePlugin.h @@ -25,7 +25,6 @@ #ifndef REMOTE_PLUGIN_H #define REMOTE_PLUGIN_H -#include "export.h" #include "MidiEvent.h" #include "VstSyncData.h" @@ -79,8 +78,8 @@ typedef int32_t key_t; #ifdef BUILD_REMOTE_PLUGIN_CLIENT -#undef EXPORT -#define EXPORT +#undef LMMS_EXPORT +#define LMMS_EXPORT #define COMPILE_REMOTE_PLUGIN_BASE #ifndef SYNC_WITH_SHM_FIFO @@ -89,6 +88,7 @@ typedef int32_t key_t; #endif #else +#include "lmms_export.h" #include #include #include @@ -138,8 +138,8 @@ public: m_shmID( -1 ), #endif m_data( NULL ), - m_dataSem( QString::null ), - m_messageSem( QString::null ), + m_dataSem( QString() ), + m_messageSem( QString() ), m_lockDepth( 0 ) { #ifdef USE_QT_SHMEM @@ -181,8 +181,8 @@ public: m_shmID( shmget( _shm_key, 0, 0 ) ), #endif m_data( NULL ), - m_dataSem( QString::null ), - m_messageSem( QString::null ), + m_dataSem( QString() ), + m_messageSem( QString() ), m_lockDepth( 0 ) { #ifdef USE_QT_SHMEM @@ -444,7 +444,7 @@ enum RemoteMessageIDs -class EXPORT RemotePluginBase +class LMMS_EXPORT RemotePluginBase { public: struct message @@ -754,13 +754,19 @@ public: ProcessWatcher( RemotePlugin * ); virtual ~ProcessWatcher() = default; - void quit() + void stop() { m_quit = true; + quit(); + } + + void reset() + { + m_quit = false; } private: - virtual void run(); + void run() override; RemotePlugin * m_plugin; volatile bool m_quit; @@ -768,7 +774,7 @@ private: } ; -class EXPORT RemotePlugin : public QObject, public RemotePluginBase +class LMMS_EXPORT RemotePlugin : public QObject, public RemotePluginBase { Q_OBJECT public: @@ -797,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 ); @@ -854,15 +860,17 @@ protected: } + bool m_failed; private: void resizeSharedProcessingMemory(); - bool m_failed; - QProcess m_process; ProcessWatcher m_watcher; + QString m_exec; + QStringList m_args; + QMutex m_commMutex; bool m_splitChannels; #ifdef USE_QT_SHMEM @@ -886,6 +894,7 @@ private: private slots: void processFinished( int exitCode, QProcess::ExitStatus exitStatus ); + void processErrored(QProcess::ProcessError err ); } ; #endif diff --git a/include/RenameDialog.h b/include/RenameDialog.h index c1d24a8a9..8f526badd 100644 --- a/include/RenameDialog.h +++ b/include/RenameDialog.h @@ -42,8 +42,8 @@ public: protected: - void keyPressEvent( QKeyEvent * _ke ); - virtual void resizeEvent(QResizeEvent * event); + void keyPressEvent( QKeyEvent * _ke ) override; + void resizeEvent(QResizeEvent * event) override; protected slots: diff --git a/include/RingBuffer.h b/include/RingBuffer.h index 3386c1175..c761616bd 100644 --- a/include/RingBuffer.h +++ b/include/RingBuffer.h @@ -32,7 +32,7 @@ #include "lmms_math.h" #include "MemoryManager.h" -class EXPORT RingBuffer : public QObject +class LMMS_EXPORT RingBuffer : public QObject { Q_OBJECT MM_OPERATORS 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/SampleBuffer.h b/include/SampleBuffer.h index 01c685fda..26e856025 100644 --- a/include/SampleBuffer.h +++ b/include/SampleBuffer.h @@ -31,7 +31,7 @@ #include -#include "export.h" +#include "lmms_export.h" #include "interpolation.h" #include "lmms_basics.h" #include "lmms_math.h" @@ -48,7 +48,7 @@ class QRect; // may need to be higher - conversely, to optimize, some may work with lower values const f_cnt_t MARGIN[] = { 64, 64, 64, 4, 4 }; -class EXPORT SampleBuffer : public QObject, public sharedObject +class LMMS_EXPORT SampleBuffer : public QObject, public sharedObject { Q_OBJECT MM_OPERATORS @@ -58,7 +58,7 @@ public: LoopOn, LoopPingPong }; - class EXPORT handleState + class LMMS_EXPORT handleState { MM_OPERATORS public: @@ -265,20 +265,22 @@ public slots: void sampleRateChanged(); private: + static sample_rate_t mixerSampleRate(); + void update( bool _keep_settings = false ); void convertIntToFloat ( int_sample_t * & _ibuf, f_cnt_t _frames, int _channels); void directFloatWrite ( sample_t * & _fbuf, f_cnt_t _frames, int _channels); - f_cnt_t decodeSampleSF( const char * _f, sample_t * & _buf, + f_cnt_t decodeSampleSF( QString _f, sample_t * & _buf, ch_cnt_t & _channels, sample_rate_t & _sample_rate ); #ifdef LMMS_HAVE_OGGVORBIS - f_cnt_t decodeSampleOGGVorbis( const char * _f, int_sample_t * & _buf, + f_cnt_t decodeSampleOGGVorbis( QString _f, int_sample_t * & _buf, ch_cnt_t & _channels, sample_rate_t & _sample_rate ); #endif - f_cnt_t decodeSampleDS( const char * _f, int_sample_t * & _buf, + f_cnt_t decodeSampleDS( QString _f, int_sample_t * & _buf, ch_cnt_t & _channels, sample_rate_t & _sample_rate ); diff --git a/include/SamplePlayHandle.h b/include/SamplePlayHandle.h index 9a051ec7b..33f5ebe52 100644 --- a/include/SamplePlayHandle.h +++ b/include/SamplePlayHandle.h @@ -1,8 +1,9 @@ + /* * SamplePlayHandle.h - play-handle for playing a sample * * Copyright (c) 2005-2014 Tobias Doerffel - * + * * This file is part of LMMS - https://lmms.io * * This program is free software; you can redistribute it and/or @@ -38,21 +39,21 @@ class AudioPort; class SamplePlayHandle : public PlayHandle { public: - SamplePlayHandle( SampleBuffer* sampleBuffer ); + SamplePlayHandle( SampleBuffer* sampleBuffer , bool ownAudioPort = true ); SamplePlayHandle( const QString& sampleFile ); 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 decf52f3f..2bad4d910 100644 --- a/include/SampleTrack.h +++ b/include/SampleTrack.h @@ -26,13 +26,19 @@ #define SAMPLE_TRACK_H #include +#include #include "AudioPort.h" +#include "FxMixer.h" +#include "FxLineLcdSpinBox.h" #include "Track.h" class EffectRackView; class Knob; class SampleBuffer; +class SampleTrackWindow; +class TrackLabelButton; +class QLineEdit; class SampleTCO : public TrackContentObject @@ -43,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"; } @@ -61,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; @@ -106,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: @@ -131,21 +137,26 @@ 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() + { + return &m_effectChannelModel; + } inline AudioPort * audioPort() { return &m_audioPort; } - virtual QString nodeName() const + QString nodeName() const override { return "sampletrack"; } @@ -153,15 +164,18 @@ public: public slots: void updateTcos(); void setPlayingTcos( bool isPlaying ); + void updateEffectChannel(); private: FloatModel m_volumeModel; FloatModel m_panningModel; + IntModel m_effectChannelModel; AudioPort m_audioPort; friend class SampleTrackView; + friend class SampleTrackWindow; } ; @@ -174,25 +188,110 @@ public: SampleTrackView( SampleTrack* Track, TrackContainerView* tcv ); virtual ~SampleTrackView(); + SampleTrackWindow * getSampleTrackWindow() + { + return m_window; + } + + SampleTrack * model() + { + return castModel(); + } + + const SampleTrack * model() const + { + return castModel(); + } + + + QMenu * createFxMenu( QString title, QString newFxLabel ) override; + public slots: void showEffects(); protected: - void modelChanged(); - virtual QString nodeName() const + void modelChanged() override; + QString nodeName() const override { return "SampleTrackView"; } + void dragEnterEvent(QDragEnterEvent *dee) override; + void dropEvent(QDropEvent *de) override; + +private slots: + void assignFxLine( int channelIndex ); + void createFxLine(); + private: - EffectRackView * m_effectRack; - QWidget * m_effWindow; + SampleTrackWindow * m_window; Knob * m_volumeKnob; Knob * m_panningKnob; + TrackLabelButton * m_tlb; + + + friend class SampleTrackWindow; + +} ; + + + +class SampleTrackWindow : public QWidget, public ModelView, public SerializingObjectHook +{ + Q_OBJECT +public: + SampleTrackWindow(SampleTrackView * tv); + virtual ~SampleTrackWindow(); + + SampleTrack * model() + { + return castModel(); + } + + const SampleTrack * model() const + { + return castModel(); + } + + void setSampleTrackView(SampleTrackView * tv); + + SampleTrackView *sampleTrackView() + { + return m_stv; + } + + +public slots: + void textChanged(const QString & new_name); + void toggleVisibility(bool on); + void updateName(); + + +protected: + // capture close-events for toggling sample-track-button + void closeEvent(QCloseEvent * ce) override; + + void saveSettings(QDomDocument & doc, QDomElement & element) override; + void loadSettings(const QDomElement & element) override; + +private: + void modelChanged() override; + + SampleTrack * m_track; + SampleTrackView * m_stv; + + // widgets on the top of an sample-track-window + QLineEdit * m_nameLineEdit; + Knob * m_volumeKnob; + Knob * m_panningKnob; + FxLineLcdSpinBox * m_effectChannelNumber; + + EffectRackView * m_effectRack; + } ; 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/SerializingObject.h b/include/SerializingObject.h index e82ac7fcb..b61794d7c 100644 --- a/include/SerializingObject.h +++ b/include/SerializingObject.h @@ -27,7 +27,7 @@ #include -#include "export.h" +#include "lmms_export.h" class QDomDocument; @@ -36,7 +36,7 @@ class QDomElement; class SerializingObjectHook; -class EXPORT SerializingObject +class LMMS_EXPORT SerializingObject { public: SerializingObject(); diff --git a/include/SetupDialog.h b/include/SetupDialog.h index 254549df1..9f9ae1b3f 100644 --- a/include/SetupDialog.h +++ b/include/SetupDialog.h @@ -1,4 +1,3 @@ - /* * SetupDialog.h - dialog for setting up LMMS * @@ -23,20 +22,20 @@ * */ + #ifndef SETUP_DIALOG_H #define SETUP_DIALOG_H #include #include +#include "AudioDevice.h" +#include "AudioDeviceSetupWidget.h" #include "LedCheckbox.h" #include "lmmsconfig.h" -#include "AudioDevice.h" #include "MidiClient.h" #include "MidiSetupWidget.h" -#include "AudioDeviceSetupWidget.h" - class QComboBox; class QLabel; @@ -48,161 +47,156 @@ class TabBar; class SetupDialog : public QDialog { Q_OBJECT + public: enum ConfigTabs { GeneralSettings, - PathSettings, PerformanceSettings, AudioSettings, - MidiSettings - } ; + MidiSettings, + PathsSettings + }; - SetupDialog( ConfigTabs _tab_to_open = GeneralSettings ); + SetupDialog(ConfigTabs tab_to_open = GeneralSettings); virtual ~SetupDialog(); protected slots: - virtual void accept(); + void accept() override; private slots: - // general settings widget - void setBufferSize( int _value ); - void resetBufSize(); + // General settings widget. + void toggleDisplaydBFS(bool enabled); + void toggleTooltips(bool enabled); + void toggleDisplayWaveform(bool enabled); + void toggleNoteLabels(bool enabled); + void toggleCompactTrackButtons(bool enabled); + void toggleOneInstrumentTrackWindow(bool enabled); + void toggleMMPZ(bool enabled); + void toggleDisableBackup(bool enabled); + void toggleOpenLastProject(bool enabled); + void setLanguage(int lang); - // path settings widget - void setWorkingDir( const QString & _wd ); - void setVSTDir( const QString & _vd ); - void setGIGDir( const QString & _gd ); - void setSF2Dir( const QString & _sfd ); - void setArtworkDir( const QString & _ad ); - void setLADSPADir( const QString & _ld ); - void setSTKDir( const QString & _sd ); - void setDefaultSoundfont( const QString & _sf ); - void setBackgroundArtwork( const QString & _ba ); - - // performance settings widget - void setAutoSaveInterval( int time ); + // Performance settings widget. + void setAutoSaveInterval(int time); void resetAutoSave(); + 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 toggleDisableAutoQuit(bool enabled); - // audio settings widget - void audioInterfaceChanged( const QString & _driver ); + // 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 ); - - - 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 ); + // MIDI settings widget. + void midiInterfaceChanged(const QString & driver); + // Paths settings widget. void openWorkingDir(); + void setWorkingDir(const QString & workingDir); void openVSTDir(); - void openGIGDir(); - void openSF2Dir(); - void openArtworkDir(); + void setVSTDir(const QString & vstDir); 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 setLanguage( int lang ); + 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_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; -} ; - - + // Paths settings widgets. + QString m_workingDir; + QString m_vstDir; + QString m_ladspaDir; + QString m_gigDir; + QString m_sf2Dir; +#ifdef LMMS_HAVE_FLUIDSYNTH + QString m_sf2File; +#endif + QString m_themeDir; + QString m_backgroundPicFile; + + QLineEdit * m_workingDirLineEdit; + QLineEdit * m_vstDirLineEdit; + QLineEdit * m_themeDirLineEdit; + QLineEdit * m_ladspaDirLineEdit; + QLineEdit * m_gigDirLineEdit; + QLineEdit * m_sf2DirLineEdit; +#ifdef LMMS_HAVE_FLUIDSYNTH + QLineEdit * m_sf2FileLineEdit; +#endif + QLineEdit * m_backgroundPicFileLineEdit; + + QLabel * restartWarningLbl; +}; #endif diff --git a/include/SideBarWidget.h b/include/SideBarWidget.h index 229f07df0..9972daa7c 100644 --- a/include/SideBarWidget.h +++ b/include/SideBarWidget.h @@ -28,6 +28,7 @@ #include #include #include +#include class SideBarWidget : public QWidget @@ -47,11 +48,13 @@ public: return m_title; } +signals: + void closeButtonClicked(); protected: - virtual void paintEvent( QPaintEvent * _pe ); - virtual void resizeEvent( QResizeEvent * _re ); - virtual void contextMenuEvent( QContextMenuEvent * ) + void paintEvent( QPaintEvent * _pe ) override; + void resizeEvent( QResizeEvent * _re ) override; + void contextMenuEvent( QContextMenuEvent * ) override { } @@ -75,6 +78,8 @@ private: QVBoxLayout * m_layout; QString m_title; QPixmap m_icon; + QPushButton * m_closeBtn; + const QSize m_buttonSize; } ; diff --git a/include/Song.h b/include/Song.h index 51b397b9c..95ea5494e 100644 --- a/include/Song.h +++ b/include/Song.h @@ -47,10 +47,10 @@ class Groove; 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 EXPORT Song : public TrackContainer +class LMMS_EXPORT Song : public TrackContainer { Q_OBJECT mapPropertyFromModel( int,getTempo,setTempo,m_tempoModel ); @@ -67,6 +67,17 @@ public: Mode_Count } ; + struct SaveOptions { + /** + * Should we discard MIDI ControllerConnections from project files? + */ + BoolModel discardMIDIConnections{false}; + + void setDefaultOptions() { + discardMIDIConnections.setValue(false); + } + }; + void clearErrors(); void collectError( const QString error ); bool hasErrors(); @@ -89,15 +100,22 @@ public: { return m_currentFrame; } + inline void setJumped( const bool jumped ) + { + m_jumped = jumped; + } + inline bool jumped() const + { + return m_jumped; + } TimeLineWidget * m_timeLine; private: float m_currentFrame; + bool m_jumped; } ; - - void processNextBuffer(); inline int getLoadingTrackCount() const @@ -139,14 +157,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 @@ -196,9 +214,23 @@ public: { return m_recording; } + + inline void setLoopRenderCount(int count) + { + if (count < 1) + m_loopRenderCount = 1; + else + m_loopRenderCount = count; + m_loopRenderRemaining = m_loopRenderCount; + } + + inline int getLoopRenderCount() const + { + return m_loopRenderCount; + } bool isExportDone() const; - std::pair getExportEndpoints() const; + int getExportProgress() const; inline void setRenderBetweenMarkers( bool renderBetweenMarkers ) { @@ -224,14 +256,14 @@ public: } void updateLength(); - tact_t length() const + bar_t length() const { return m_length; } bpm_t getTempo(); - virtual AutomationPattern * tempoAutomationPattern(); + AutomationPattern * tempoAutomationPattern() override; AutomationTrack * globalAutomationTrack() { @@ -244,7 +276,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(); @@ -281,7 +313,7 @@ public: return m_modified; } - virtual QString nodeName() const + QString nodeName() const override { return "song"; } @@ -309,6 +341,11 @@ public: void exportProjectMidi(QString const & exportFileName) const; inline void setLoadOnLauch(bool value) { m_loadOnLaunch = value; } + SaveOptions &getSaveOptions() { + return m_saveOptions; + } + + bool isSavingProject() const; public slots: void playSong(); @@ -354,9 +391,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 @@ -386,7 +423,7 @@ private: IntModel m_tempoModel; MeterModel m_timeSigModel; - int m_oldTicksPerTact; + int m_oldTicksPerBar; IntModel m_masterVolumeModel; IntModel m_masterPitchModel; @@ -406,24 +443,34 @@ private: volatile bool m_playing; volatile bool m_paused; + bool m_savingProject; bool m_loadingProject; bool m_isCancelled; + SaveOptions m_saveOptions; + QStringList m_errors; 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; - + + int m_loopRenderCount; + int m_loopRenderRemaining; + MidiTime m_exportSongBegin; + MidiTime m_exportLoopBegin; + MidiTime m_exportLoopEnd; + MidiTime m_exportSongEnd; + MidiTime m_exportEffectiveLength; friend class LmmsCore; friend class SongEditor; @@ -434,9 +481,9 @@ signals: void projectLoaded(); void playbackStateChanged(); void playbackPositionChanged(); - void lengthChanged( int tacts ); + void lengthChanged( int bars ); void tempoChanged( bpm_t newBPM ); - void timeSignatureChanged( int oldTicksPerTact, int ticksPerTact ); + void timeSignatureChanged( int oldTicksPerBar, int ticksPerBar ); void controllerAdded( Controller * ); void controllerRemoved( Controller * ); void updateSampleTracks(); diff --git a/include/SongEditor.h b/include/SongEditor.h index e31d0f862..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,24 +69,34 @@ 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; + float getSnapSize() const; + QString getSnapSizeString() const; public slots: void scrolled( int new_pos ); + void selectRegionFromPixels(int xStart, int xEnd); + void stopSelectRegion(); + void updateRubberband(); void setEditMode( EditMode mode ); void setEditModeDraw(); void setEditModeSelect(); + void toggleProportionalSnap(); void updatePosition( const MidiTime & t ); void updatePositionLine(); void selectAllTcos( bool select ); protected: - virtual void closeEvent( QCloseEvent * ce ); + void closeEvent( QCloseEvent * ce ) override; + void mousePressEvent(QMouseEvent * me) override; + void mouseMoveEvent(QMouseEvent * me) override; + void mouseReleaseEvent(QMouseEvent * me) override; private slots: void setHighQuality( bool ); @@ -106,10 +116,13 @@ private slots: void zoomingChanged(); private: - virtual void keyPressEvent( QKeyEvent * ke ); - virtual void wheelEvent( QWheelEvent * we ); + void keyPressEvent( QKeyEvent * ke ) override; + void wheelEvent( QWheelEvent * we ) override; - virtual bool allowRubberband() const; + bool allowRubberband() const override; + + int trackIndexFromSelectionPoint(int yPos); + int indexOfTrackView(const TrackView* tv); Song * m_song; @@ -130,18 +143,27 @@ private: positionLine * m_positionLine; ComboBoxModel* m_zoomingModel; + ComboBoxModel* m_snappingModel; + bool m_proportionalSnap; static const QVector m_zoomLevels; bool m_scrollBack; bool m_smoothScroll; - int m_widgetWidthTotal; EditMode m_mode; EditMode m_ctrlMode; // mode they were in before they hit ctrl - friend class SongEditorWindow; + 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; } ; @@ -153,33 +175,37 @@ class SongEditorWindow : public Editor public: SongEditorWindow( Song* song ); - QSize sizeHint() const; + QSize sizeHint() const override; SongEditor* m_editor; protected: - virtual void resizeEvent( QResizeEvent * event ); + 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(); + void updateSnapLabel(); + signals: void playTriggered(); 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; QAction* m_addAutomationTrackAction; + QAction* m_setProportionalSnapAction; ActionGroup * m_editModeGroup; QAction* m_drawModeAction; @@ -187,6 +213,8 @@ private: QAction* m_crtlAction; ComboBox * m_zoomingComboBox; + ComboBox * m_snappingComboBox; + QLabel* m_snapSizeLabel; }; #endif diff --git a/include/StepRecorder.h b/include/StepRecorder.h new file mode 100644 index 000000000..b9653b1bb --- /dev/null +++ b/include/StepRecorder.h @@ -0,0 +1,143 @@ +/* + * 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 STEP_RECORDER_H +#define STEP_RECORDER_H + +#include +#include +#include +#include + +#include "Note.h" +#include "lmms_basics.h" +#include "Pattern.h" + +class PianoRoll; +class StepRecorderWidget; + +class StepRecorder : public QObject +{ + Q_OBJECT + + public: + StepRecorder(PianoRoll& pianoRoll, StepRecorderWidget& stepRecorderWidget); + + void initialize(); + void start(const MidiTime& currentPosition,const MidiTime& stepLength); + void stop(); + void notePressed(const Note & n); + void noteReleased(const Note & n); + bool keyPressEvent(QKeyEvent* ke); + bool mousePressEvent(QMouseEvent* ke); + void setCurrentPattern(Pattern* newPattern); + void setStepsLength(const MidiTime& newLength); + + QVector getCurStepNotes(); + + bool isRecording() const + { + return m_isRecording; + } + + QColor curStepNoteColor() const + { + return QColor(245,3,139); // radiant pink + } + + private slots: + void removeNotesReleasedForTooLong(); + + private: + void stepForwards(); + void stepBackwards(); + + void applyStep(); + void dismissStep(); + void prepareNewStep(); + + MidiTime getCurStepEndPos(); + + void updateCurStepNotes(); + void updateWidget(); + + bool allCurStepNotesReleased(); + + PianoRoll& m_pianoRoll; + StepRecorderWidget& m_stepRecorderWidget; + + bool m_isRecording = false; + MidiTime m_curStepStartPos = 0; + MidiTime m_curStepEndPos = 0; + + MidiTime m_stepsLength; + MidiTime m_curStepLength; // current step length refers to the step currently recorded. it may defer from m_stepsLength + // since the user can make current step larger + + QTimer m_updateReleasedTimer; + + Pattern* m_pattern; + + class StepNote + { + public: + StepNote(const Note & note) : m_note(note), m_pressed(true) {}; + + void setPressed() + { + m_pressed = true; + } + + void setReleased() + { + m_pressed = false; + releasedTimer.start(); + } + + int timeSinceReleased() + { + return releasedTimer.elapsed(); + } + + bool isPressed() const + { + return m_pressed; + } + + bool isReleased() const + { + return !m_pressed; + } + + Note m_note; + + private: + bool m_pressed; + QTime releasedTimer; + } ; + + QVector m_curStepNotes; // contains the current recorded step notes (i.e. while user still press the notes; before they are applied to the pattern) + + StepNote* findCurStepNote(const int key); + + bool m_isStepInProgress = false; +}; + +#endif //STEP_RECORDER_H \ No newline at end of file diff --git a/include/StepRecorderWidget.h b/include/StepRecorderWidget.h new file mode 100644 index 000000000..14cfc2eed --- /dev/null +++ b/include/StepRecorderWidget.h @@ -0,0 +1,92 @@ +/* + * StepRecorderWidget.h - widget that provide gui markers for step recording + * + * 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 STEP_RECOREDER_WIDGET_H +#define STEP_RECOREDER_WIDGET_H + +#include "lmms_basics.h" +#include "Note.h" + +#include +#include +#include + +class StepRecorderWidget : public QWidget +{ + Q_OBJECT + +public: + StepRecorderWidget( + QWidget * parent, + const int ppb, + const int marginTop, + const int marginBottom, + const int marginLeft, + const int marginRight); + + //API used by PianoRoll + void setPixelsPerBar(int ppb); + void setCurrentPosition(MidiTime currentPosition); + void setBottomMargin(const int marginBottom); + + //API used by StepRecorder + void setStepsLength(MidiTime stepsLength); + void setStartPosition(MidiTime pos); + void setEndPosition(MidiTime pos); + + void showHint(); + +private: + void paintEvent(QPaintEvent * pe) override; + + int xCoordOfTick(int tick); + + void drawVerLine(QPainter* painter, int x, const QColor& color, int top, int bottom); + void drawVerLine(QPainter* painter, const MidiTime& pos, const QColor& color, int top, int bottom); + + void updateBoundaries(); + + MidiTime m_stepsLength; + MidiTime m_curStepStartPos; + MidiTime m_curStepEndPos; + + int m_ppb; // pixels per bar + MidiTime m_currentPosition; // current position showed by on PianoRoll + + QColor m_colorLineStart; + QColor m_colorLineEnd; + + // boundaries within piano roll window + int m_top; + int m_bottom; + int m_left; + int m_right; + + const int m_marginTop; + int m_marginBottom; // not const since can change on resize of edit-note area + const int m_marginLeft; + const int m_marginRight; + +signals: + void positionChanged(const MidiTime & t); +} ; + +#endif //STEP_RECOREDER_WIDGET_H diff --git a/include/StringPairDrag.h b/include/StringPairDrag.h index a69d7d143..cebc3089a 100644 --- a/include/StringPairDrag.h +++ b/include/StringPairDrag.h @@ -31,12 +31,12 @@ #include #include -#include "export.h" +#include "lmms_export.h" class QPixmap; -class EXPORT StringPairDrag : public QDrag +class LMMS_EXPORT StringPairDrag : public QDrag { public: StringPairDrag( const QString & _key, const QString & _value, diff --git a/include/SubWindow.h b/include/SubWindow.h index 24485109e..148cf2c99 100644 --- a/include/SubWindow.h +++ b/include/SubWindow.h @@ -30,11 +30,10 @@ #include #include #include -#include #include #include -#include "export.h" +#include "lmms_export.h" class QMoveEvent; class QResizeEvent; @@ -48,7 +47,7 @@ class QWidget; * for cusomizing the title bar appearance, lmms implements its own subwindow * class. */ -class EXPORT SubWindow : public QMdiSubWindow +class LMMS_EXPORT SubWindow : public QMdiSubWindow { Q_OBJECT Q_PROPERTY( QBrush activeColor READ activeColor WRITE setActiveColor ) @@ -68,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(); @@ -92,7 +91,6 @@ private: bool m_hasFocus; static void elideText( QLabel *label, QString text ); - bool isMaximized(); void adjustTitleBar(); private slots: diff --git a/include/TabBar.h b/include/TabBar.h index 4ef0b1ac7..48b429bd5 100644 --- a/include/TabBar.h +++ b/include/TabBar.h @@ -30,13 +30,13 @@ #include #include -#include "export.h" +#include "lmms_export.h" class TabButton; -class EXPORT TabBar : public QWidget +class LMMS_EXPORT TabBar : public QWidget { Q_OBJECT public: diff --git a/include/TabWidget.h b/include/TabWidget.h index dacd2648b..0cf15155b 100644 --- a/include/TabWidget.h +++ b/include/TabWidget.h @@ -36,7 +36,10 @@ class TabWidget : public QWidget { Q_OBJECT public: - TabWidget( const QString & _caption, QWidget * _parent, bool usePixmap = false ); + //! @param resizable If true, the widget resizes to fit the size of all tabs + //! If false, all child widget will be cut down to the TabWidget's size + TabWidget( const QString & _caption, QWidget * _parent, + bool usePixmap = false, bool resizable = false ); virtual ~TabWidget() = default; void addTab( QWidget * w, const QString & name, const char *pixmap = NULL, int idx = -1 ); @@ -69,12 +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 ); - + 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 @@ -88,6 +92,7 @@ private: widgetStack m_widgets; + bool m_resizable; int m_activeTab; QString m_caption; // Tab caption, used as the tooltip text on icon tabs quint8 m_tabbarHeight; // The height of the tab bar diff --git a/include/TemplatesMenu.h b/include/TemplatesMenu.h new file mode 100644 index 000000000..049f1f47e --- /dev/null +++ b/include/TemplatesMenu.h @@ -0,0 +1,21 @@ +#ifndef TEMPLATESMENU_H +#define TEMPLATESMENU_H + +#include +#include + +class TemplatesMenu : public QMenu +{ + Q_OBJECT +public: + TemplatesMenu(QWidget *parent = nullptr); + virtual ~TemplatesMenu() = default; + +private slots: + static void createNewProjectFromTemplate(QAction * _action); + void fillTemplatesMenu(); + void addTemplatesFromDir( const QDir& dir ); + +}; + +#endif // TEMPLATESMENU_H diff --git a/include/TempoSyncKnob.h b/include/TempoSyncKnob.h index 343deb067..416abe1fc 100644 --- a/include/TempoSyncKnob.h +++ b/include/TempoSyncKnob.h @@ -34,7 +34,7 @@ class MeterDialog; -class EXPORT TempoSyncKnob : public Knob +class LMMS_EXPORT TempoSyncKnob : public Knob { Q_OBJECT public: @@ -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 893e23eb4..b9512aa1a 100644 --- a/include/TempoSyncKnobModel.h +++ b/include/TempoSyncKnobModel.h @@ -30,9 +30,10 @@ class QAction; -class EXPORT TempoSyncKnobModel : public FloatModel +class LMMS_EXPORT TempoSyncKnobModel : public FloatModel { Q_OBJECT + MODEL_IS_VISITABLE public: enum TempoSyncMode { @@ -51,10 +52,10 @@ public: const float _max, const float _step, const float _scale, Model * _parent, const QString & _display_name = QString() ); - virtual ~TempoSyncKnobModel(); + ~TempoSyncKnobModel() override; - void saveSettings( QDomDocument & _doc, QDomElement & _this, const QString& name ); - void loadSettings( const QDomElement & _this, const QString& name ); + void saveSettings( QDomDocument & _doc, QDomElement & _this, const QString& name ) override; + void loadSettings( const QDomElement & _this, const QString& name ) override; TempoSyncMode syncMode() const { diff --git a/include/TextFloat.h b/include/TextFloat.h index 673e40e63..8f940c591 100644 --- a/include/TextFloat.h +++ b/include/TextFloat.h @@ -29,10 +29,10 @@ #include #include -#include "export.h" +#include "lmms_export.h" -class EXPORT TextFloat : public QWidget +class LMMS_EXPORT TextFloat : public QWidget { Q_OBJECT public: @@ -66,8 +66,8 @@ public: protected: - virtual void paintEvent( QPaintEvent * _me ); - virtual void mousePressEvent( QMouseEvent * _me ); + void paintEvent( QPaintEvent * _me ) override; + void mousePressEvent( QMouseEvent * _me ) override; private: diff --git a/include/TimeDisplayWidget.h b/include/TimeDisplayWidget.h index 175f159c9..e7e5cb210 100644 --- a/include/TimeDisplayWidget.h +++ b/include/TimeDisplayWidget.h @@ -41,7 +41,7 @@ public: protected: - virtual void mousePressEvent( QMouseEvent* mouseEvent ); + void mousePressEvent( QMouseEvent* mouseEvent ) override; private slots: diff --git a/include/TimeLineWidget.h b/include/TimeLineWidget.h index 7629694ca..bc0881f82 100644 --- a/include/TimeLineWidget.h +++ b/include/TimeLineWidget.h @@ -72,15 +72,15 @@ public: } ; - TimeLineWidget(int xoff, int yoff, float ppt, Song::PlayPos & pos, + TimeLineWidget(int xoff, int yoff, float ppb, Song::PlayPos & pos, const MidiTime & begin, Song::PlayModes mode, QWidget * parent); virtual ~TimeLineWidget(); inline QColor const & getBarLineColor() const { return m_barLineColor; } - inline void setBarLineColor(QColor const & tactLineColor) { m_barLineColor = tactLineColor; } + inline void setBarLineColor(QColor const & barLineColor) { m_barLineColor = barLineColor; } inline QColor const & getBarNumberColor() const { return m_barNumberColor; } - inline void setBarNumberColor(QColor const & tactNumberColor) { m_barNumberColor = tactNumberColor; } + inline void setBarNumberColor(QColor const & barNumberColor) { m_barNumberColor = barNumberColor; } inline QColor const & getInactiveLoopColor() const { return m_inactiveLoopColor; } inline void setInactiveLoopColor(QColor const & inactiveLoopColor) { m_inactiveLoopColor = inactiveLoopColor; } @@ -135,27 +135,27 @@ public: m_loopPos[0] : m_loopPos[1]; } - inline void savePos( const MidiTime & _pos ) + inline void savePos( const MidiTime & pos ) { - m_savedPos = _pos; + m_savedPos = pos; } inline const MidiTime & savedPos() const { return m_savedPos; } - inline void setPixelsPerTact( float _ppt ) + inline void setPixelsPerBar( float ppb ) { - m_ppt = _ppt; + m_ppb = ppb; update(); } void addToolButtons(QToolBar* _tool_bar ); - virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent ); - virtual void loadSettings( const QDomElement & _this ); - inline virtual QString nodeName() const + void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override; + void loadSettings( const QDomElement & _this ) override; + inline QString nodeName() const override { return "timeline"; } @@ -163,7 +163,7 @@ public: inline int markerX( const MidiTime & _t ) const { return m_xOffset + static_cast( ( _t - m_begin ) * - m_ppt / MidiTime::ticksPerTact() ); + m_ppb / MidiTime::ticksPerBar() ); } signals: @@ -184,10 +184,10 @@ public slots: protected: - virtual void paintEvent( QPaintEvent * _pe ); - virtual void mousePressEvent( QMouseEvent * _me ); - virtual void mouseMoveEvent( QMouseEvent * _me ); - virtual void mouseReleaseEvent( QMouseEvent * _me ); + void paintEvent( QPaintEvent * _pe ) override; + void mousePressEvent( QMouseEvent * _me ) override; + void mouseMoveEvent( QMouseEvent * _me ) override; + void mouseReleaseEvent( QMouseEvent * _me ) override; private: @@ -214,7 +214,7 @@ private: int m_xOffset; int m_posMarkerX; - float m_ppt; + float m_ppb; Song::PlayPos & m_pos; const MidiTime & m_begin; const Song::PlayModes m_mode; diff --git a/include/ToolPlugin.h b/include/ToolPlugin.h index bc8b3cf18..8a65147ac 100644 --- a/include/ToolPlugin.h +++ b/include/ToolPlugin.h @@ -29,7 +29,7 @@ #include "Plugin.h" -class EXPORT ToolPlugin : public Plugin +class LMMS_EXPORT ToolPlugin : public Plugin { public: ToolPlugin( const Descriptor * _descriptor, Model * _parent ); diff --git a/include/ToolPluginView.h b/include/ToolPluginView.h index de0f8bb1e..2b64caaaf 100644 --- a/include/ToolPluginView.h +++ b/include/ToolPluginView.h @@ -30,7 +30,7 @@ class ToolPlugin; -class EXPORT ToolPluginView : public PluginView +class LMMS_EXPORT ToolPluginView : public PluginView { public: ToolPluginView( ToolPlugin * _toolPlugin ); diff --git a/include/ToolTip.h b/include/ToolTip.h index 76b571bca..7f769a05b 100644 --- a/include/ToolTip.h +++ b/include/ToolTip.h @@ -28,14 +28,14 @@ #include -#include "export.h" +#include "lmms_export.h" class QWidget; struct ToolTip { - static void EXPORT add( QWidget * _w, const QString & _txt ); + static void LMMS_EXPORT add( QWidget * _w, const QString & _txt ); } ; diff --git a/include/Track.h b/include/Track.h index 6ac6e390f..70e49a1c6 100644 --- a/include/Track.h +++ b/include/Track.h @@ -29,7 +29,6 @@ #include #include #include -#include #include #include @@ -73,7 +72,7 @@ const int DEFAULT_TRACK_HEIGHT = 32; const int TCO_BORDER_WIDTH = 2; -class TrackContentObject : public Model, public JournallingObject +class LMMS_EXPORT TrackContentObject : public Model, public JournallingObject { Q_OBJECT MM_OPERATORS @@ -99,7 +98,7 @@ public: emit dataChanged(); } - virtual QString displayName() const + QString displayName() const override { return name(); } @@ -215,6 +214,12 @@ public: { return m_tco; } + + inline TrackView * getTrackView() + { + return m_trackView; + } + // qproperty access func QColor mutedColor() const; QColor mutedBackgroundColor() const; @@ -236,37 +241,33 @@ public: // access needsUpdate member variable bool needsUpdate(); void setNeedsUpdate( bool b ); - + public slots: virtual bool close(); void cut(); void remove(); - virtual void update(); + void update() override; protected: virtual void constructContextMenu( QMenu * ) { } - virtual void contextMenuEvent( QContextMenuEvent * cme ); - virtual void dragEnterEvent( QDragEnterEvent * dee ); - virtual void dropEvent( QDropEvent * de ); - virtual void leaveEvent( QEvent * e ); - virtual void mousePressEvent( QMouseEvent * me ); - virtual void mouseMoveEvent( QMouseEvent * me ); - virtual void mouseReleaseEvent( QMouseEvent * me ); - virtual void resizeEvent( QResizeEvent * re ) + void contextMenuEvent( QContextMenuEvent * cme ) override; + void dragEnterEvent( QDragEnterEvent * dee ) override; + void dropEvent( QDropEvent * de ) override; + void leaveEvent( QEvent * e ) override; + void mousePressEvent( QMouseEvent * me ) override; + void mouseMoveEvent( QMouseEvent * me ) override; + void mouseReleaseEvent( QMouseEvent * me ) override; + void resizeEvent( QResizeEvent * re ) override { m_needsUpdate = true; selectableObject::resizeEvent( re ); } - float pixelsPerTact(); + float pixelsPerBar(); - inline TrackView * getTrackView() - { - return m_trackView; - } DataFile createTCODataFiles(const QVector & tcos) const; @@ -297,6 +298,9 @@ private: Actions m_action; QPoint m_initialMousePos; QPoint m_initialMouseGlobalPos; + MidiTime m_initialTCOPos; + MidiTime m_initialTCOEnd; + QVector m_initialOffsets; TextFloat * m_hint; @@ -311,14 +315,17 @@ private: bool m_gradient; bool m_needsUpdate; - inline void setInitialMousePos( QPoint pos ) + inline void setInitialPos( QPoint pos ) { m_initialMousePos = pos; m_initialMouseGlobalPos = mapToGlobal( pos ); + m_initialTCOPos = m_tco->startPosition(); + m_initialTCOEnd = m_initialTCOPos + m_tco->length(); } + void setInitialOffsets(); bool mouseMovedDistance( QMouseEvent * me, int distance ); - + MidiTime draggedTCOPos( QMouseEvent * me ); } ; @@ -352,7 +359,7 @@ public: } } - bool canPasteSelection( MidiTime tcoPos, const QMimeData * mimeData ); + bool canPasteSelection( MidiTime tcoPos, const QDropEvent *de ); bool pasteSelection( MidiTime tcoPos, QDropEvent * de ); MidiTime endPosition( const MidiTime & posStart ); @@ -374,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) } @@ -428,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: @@ -463,7 +470,7 @@ signals: // base-class for all tracks -class EXPORT Track : public Model, public JournallingObject +class LMMS_EXPORT Track : public Model, public JournallingObject { Q_OBJECT MM_OPERATORS @@ -511,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() { @@ -540,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 @@ -557,20 +564,20 @@ public: return m_name; } - virtual QString displayName() const + QString displayName() const override { return name(); } using Model::dataChanged; - inline int getHeight() + inline int getHeight() { return m_height >= MINIMAL_TRACK_HEIGHT - ? m_height + ? m_height : DEFAULT_TRACK_HEIGHT; } - inline void setHeight( int height ) + inline void setHeight( int height ) { m_height = height; } @@ -675,38 +682,42 @@ public: virtual void update(); + // Create a menu for assigning/creating channels for this track + // Currently instrument track and sample track supports it + virtual QMenu * createFxMenu(QString title, QString newFxLabel); + public slots: virtual bool close(); 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 33569c9d9..fd853a73c 100644 --- a/include/TrackContainer.h +++ b/include/TrackContainer.h @@ -37,7 +37,7 @@ class InstrumentTrack; class TrackContainerView; -class EXPORT TrackContainer : public Model, public JournallingObject +class LMMS_EXPORT TrackContainer : public Model, public JournallingObject { Q_OBJECT public: @@ -51,9 +51,9 @@ public: TrackContainer(); virtual ~TrackContainer(); - virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent ); + void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override; - virtual void loadSettings( const QDomElement & _this ); + void loadSettings( const QDomElement & _this ) override; virtual AutomationPattern * tempoAutomationPattern() @@ -124,7 +124,7 @@ public: { } - virtual QString nodeName() const + QString nodeName() const override { return "DummyTrackContainer"; } diff --git a/include/TrackContainerView.h b/include/TrackContainerView.h index 67575583b..6e952189b 100644 --- a/include/TrackContainerView.h +++ b/include/TrackContainerView.h @@ -49,30 +49,30 @@ public: TrackContainerView( TrackContainer* tc ); virtual ~TrackContainerView(); - virtual void saveSettings( QDomDocument & _doc, QDomElement & _this ); - virtual void loadSettings( const QDomElement & _this ); + void saveSettings( QDomDocument & _doc, QDomElement & _this ) override; + void loadSettings( const QDomElement & _this ) override; QScrollArea * contentWidget() { - return( m_scrollArea ); + return m_scrollArea; } inline const MidiTime & currentPosition() const { - return( m_currentPosition ); + return m_currentPosition; } virtual bool fixedTCOs() const { - return( false ); + return false; } - inline float pixelsPerTact() const + inline float pixelsPerBar() const { - return( m_ppt ); + return m_ppb; } - void setPixelsPerTact( int _ppt ); + void setPixelsPerBar( int ppb ); const TrackView * trackViewAt( const int _y ) const; @@ -80,12 +80,12 @@ public: inline bool rubberBandActive() const { - return( m_rubberBand->isEnabled() && m_rubberBand->isVisible() ); + return m_rubberBand->isEnabled() && m_rubberBand->isVisible(); } inline QVector selectedObjects() { - return( m_rubberBand->selectedObjects() ); + return m_rubberBand->selectedObjects(); } @@ -116,9 +116,9 @@ public: void clearAllTracks(); - virtual QString nodeName() const + QString nodeName() const override { - return( "trackcontainerview" ); + return "trackcontainerview"; } @@ -129,27 +129,19 @@ public slots: TrackView * createTrackView( Track * _t ); void deleteTrackView( TrackView * _tv ); - virtual void dropEvent( QDropEvent * _de ); - virtual void dragEnterEvent( QDragEnterEvent * _dee ); - /// - /// \brief selectRegionFromPixels - /// \param x - /// \param y - /// Use the rubber band to select TCO from all tracks using x, y pixels - void selectRegionFromPixels(int xStart, int xEnd); + void dropEvent( QDropEvent * _de ) override; + void dragEnterEvent( QDragEnterEvent * _dee ) override; /// /// \brief stopRubberBand /// Removes the rubber band from display when finished with. void stopRubberBand(); -protected: - static const int DEFAULT_PIXELS_PER_TACT = 16; - virtual void mousePressEvent( QMouseEvent * _me ); - virtual void mouseMoveEvent( QMouseEvent * _me ); - virtual void mouseReleaseEvent( QMouseEvent * _me ); - virtual void resizeEvent( QResizeEvent * ); +protected: + static const int DEFAULT_PIXELS_PER_BAR = 16; + + void resizeEvent( QResizeEvent * ) override; MidiTime m_currentPosition; @@ -168,7 +160,7 @@ private: virtual ~scrollArea(); protected: - virtual void wheelEvent( QWheelEvent * _we ); + void wheelEvent( QWheelEvent * _we ) override; private: TrackContainerView* m_trackContainerView; @@ -183,10 +175,10 @@ private: scrollArea * m_scrollArea; QVBoxLayout * m_scrollLayout; - float m_ppt; + float m_ppb; RubberBand * m_rubberBand; - QPoint m_origin; + signals: @@ -202,7 +194,7 @@ public: InstrumentLoaderThread( QObject *parent = 0, InstrumentTrack *it = 0, QString name = "" ); - void run(); + void run() override; private: InstrumentTrack *m_it; diff --git a/include/TrackLabelButton.h b/include/TrackLabelButton.h index f1059bdbf..7d9726feb 100644 --- a/include/TrackLabelButton.h +++ b/include/TrackLabelButton.h @@ -49,13 +49,13 @@ public slots: protected: - virtual void dragEnterEvent( QDragEnterEvent * _dee ); - virtual void dropEvent( QDropEvent * _de ); - virtual void mousePressEvent( QMouseEvent * _me ); - virtual void mouseDoubleClickEvent( QMouseEvent * _me ); - virtual void mouseReleaseEvent( QMouseEvent * _me ); - virtual void paintEvent( QPaintEvent * _pe ); - virtual void resizeEvent( QResizeEvent * _re ); + void dragEnterEvent( QDragEnterEvent * _dee ) override; + void dropEvent( QDropEvent * _de ) override; + void mousePressEvent( QMouseEvent * _me ) override; + void mouseDoubleClickEvent( QMouseEvent * _me ) override; + void mouseReleaseEvent( QMouseEvent * _me ) override; + void paintEvent( QPaintEvent * _pe ) override; + void resizeEvent( QResizeEvent * _re ) override; private: diff --git a/include/TrackRenameLineEdit.h b/include/TrackRenameLineEdit.h index 6883b9b05..e681a2d21 100644 --- a/include/TrackRenameLineEdit.h +++ b/include/TrackRenameLineEdit.h @@ -37,7 +37,7 @@ public: void show(); protected: - virtual void keyPressEvent( QKeyEvent * ke ); + void keyPressEvent( QKeyEvent * ke ) override; private: QString m_oldName; diff --git a/include/ValueBuffer.h b/include/ValueBuffer.h index 1e714d455..f9869de88 100644 --- a/include/ValueBuffer.h +++ b/include/ValueBuffer.h @@ -29,9 +29,9 @@ #include #include "MemoryManager.h" -#include "export.h" +#include "lmms_export.h" -class EXPORT ValueBuffer : public std::vector +class LMMS_EXPORT ValueBuffer : public std::vector { MM_OPERATORS public: diff --git a/include/VersionedSaveDialog.h b/include/VersionedSaveDialog.h index 781c6b71c..2e30e9f09 100644 --- a/include/VersionedSaveDialog.h +++ b/include/VersionedSaveDialog.h @@ -29,15 +29,25 @@ #define VERSIONEDSAVEDIALOG_H #include "FileDialog.h" +#include "Song.h" class QLineEdit; +class LedCheckBox; +class SaveOptionsWidget : public QWidget { +public: + SaveOptionsWidget(Song::SaveOptions &saveOptions); + +private: + LedCheckBox *m_discardMIDIConnectionsCheckbox; +}; class VersionedSaveDialog : public FileDialog { Q_OBJECT public: explicit VersionedSaveDialog( QWidget *parent = 0, + QWidget *saveOptionsWidget = nullptr, const QString &caption = QString(), const QString &directory = QString(), const QString &filter = QString() ); diff --git a/include/VisualizationWidget.h b/include/VisualizationWidget.h index 4d73f052d..85825975a 100644 --- a/include/VisualizationWidget.h +++ b/include/VisualizationWidget.h @@ -36,6 +36,9 @@ class VisualizationWidget : public QWidget { Q_OBJECT public: + Q_PROPERTY( QColor normalColor READ normalColor WRITE setNormalColor ) + Q_PROPERTY( QColor warningColor READ warningColor WRITE setWarningColor ) + Q_PROPERTY( QColor clippingColor READ clippingColor WRITE setClippingColor ) enum visualizationTypes { Simple // add more here @@ -47,15 +50,26 @@ public: void setActive( bool _active ); + QColor const & normalColor() const; + void setNormalColor(QColor const & normalColor); + + QColor const & warningColor() const; + void setWarningColor(QColor const & warningColor); + + QColor const & clippingColor() const; + void setClippingColor(QColor const & clippingColor); + protected: - virtual void paintEvent( QPaintEvent * _pe ); - virtual void mousePressEvent( QMouseEvent * _me ); + void paintEvent( QPaintEvent * _pe ) override; + void mousePressEvent( QMouseEvent * _me ) override; protected slots: void updateAudioBuffer( const surroundSampleFrame * buffer ); +private: + QColor const & determineLineColor(float level) const; private: QPixmap s_background; @@ -64,6 +78,9 @@ private: sampleFrame * m_buffer; bool m_active; + QColor m_normalColor; + QColor m_warningColor; + QColor m_clippingColor; } ; #endif diff --git a/include/VstSyncController.h b/include/VstSyncController.h index c9190a9d8..33f2ee036 100644 --- a/include/VstSyncController.h +++ b/include/VstSyncController.h @@ -39,7 +39,7 @@ public: VstSyncController(); ~VstSyncController(); - void setAbsolutePosition( int ticks ); + void setAbsolutePosition( double ticks ); void setPlaybackState( bool enabled ) { @@ -61,6 +61,11 @@ public: m_syncData->isCycle = false; } + void setPlaybackJumped( bool jumped ) + { + m_syncData->m_playbackJumped = jumped; + } + void update(); diff --git a/include/VstSyncData.h b/include/VstSyncData.h index a4c5db80b..6c2f1bbd2 100644 --- a/include/VstSyncData.h +++ b/include/VstSyncData.h @@ -41,14 +41,15 @@ struct VstSyncData { - bool isPlaying; - float ppqPos; + double ppqPos; int timeSigNumer; int timeSigDenom; + bool isPlaying; bool isCycle; bool hasSHM; float cycleStart; float cycleEnd; + bool m_playbackJumped; int m_bufferSize; int m_sampleRate; int m_bpm; diff --git a/include/aeffectx.h b/include/aeffectx.h index b2f8f0c6d..133d925ac 100644 --- a/include/aeffectx.h +++ b/include/aeffectx.h @@ -28,6 +28,9 @@ #include +// Calling convention +#define VST_CALL_CONV __cdecl + #define CCONST(a, b, c, d)( ( ( (int32_t) a ) << 24 ) | \ ( ( (int32_t) b ) << 16 ) | \ ( ( (int32_t) c ) << 8 ) | \ @@ -205,13 +208,13 @@ public: // 00-03 int32_t magic; // dispatcher 04-07 - intptr_t (* dispatcher)( AEffect * , int32_t , int32_t , intptr_t, void * , float ); + intptr_t (VST_CALL_CONV * dispatcher)( AEffect * , int32_t , int32_t , intptr_t, void * , float ); // process, quite sure 08-0b - void (* process)( AEffect * , float * * , float * * , int32_t ); + void (VST_CALL_CONV * process)( AEffect * , float * * , float * * , int32_t ); // setParameter 0c-0f - void (* setParameter)( AEffect * , int32_t , float ); + void (VST_CALL_CONV * setParameter)( AEffect * , int32_t , float ); // getParameter 10-13 - float (* getParameter)( AEffect * , int32_t ); + float (VST_CALL_CONV * getParameter)( AEffect * , int32_t ); // programs 14-17 int32_t numPrograms; // Params 18-1b @@ -238,7 +241,7 @@ public: // Don't know 4c-4f char unknown1[4]; // processReplacing 50-53 - void (* processReplacing)( AEffect * , float * * , float * * , int ); + void (VST_CALL_CONV * processReplacing)( AEffect * , float * * , float * * , int ); } ; @@ -281,7 +284,7 @@ public: -typedef intptr_t (* audioMasterCallback)( AEffect * , int32_t, int32_t, intptr_t, void * , float ); +typedef intptr_t (VST_CALL_CONV * audioMasterCallback)( AEffect * , int32_t, int32_t, intptr_t, void * , float ); #endif diff --git a/include/embed.h b/include/embed.h index 57ca743cd..a99c35c0a 100644 --- a/include/embed.h +++ b/include/embed.h @@ -28,15 +28,25 @@ #include #include -#include "export.h" +#include "lmms_export.h" #include "lmms_basics.h" namespace embed { -QPixmap EXPORT getIconPixmap( const QString& _name, int _w = -1, int _h = -1 ); -QString EXPORT getText( const char * _name ); +/** + * Return an image for the icon pixmap cache. + * + * @param _name Identifier for the pixmap. If it is not in the icon pixmap + * cache, it will be loaded from the artwork QDir search paths (exceptions are + * compiled-in XPMs, you need to provide @p xpm for loading them). + * @param xpm Must be XPM data if the source should be raw XPM data instead of + * a file + */ +QPixmap LMMS_EXPORT getIconPixmap( const QString& _name, + int _w = -1, int _h = -1 , const char** xpm = nullptr ); +QString LMMS_EXPORT getText( const char * _name ); } @@ -45,9 +55,10 @@ QString EXPORT getText( const char * _name ); namespace PLUGIN_NAME { -inline QPixmap getIconPixmap( const QString& _name, int _w = -1, int _h = -1 ) +inline QPixmap getIconPixmap( const QString& _name, + int _w = -1, int _h = -1, const char** xpm = nullptr ) { - return embed::getIconPixmap(QString("%1/%2").arg(STRINGIFY(PLUGIN_NAME), _name), _w, _h); + return embed::getIconPixmap(QString("%1/%2").arg(STRINGIFY(PLUGIN_NAME), _name), _w, _h, xpm); } //QString getText( const char * _name ); @@ -60,12 +71,15 @@ class PixmapLoader { public: PixmapLoader( const PixmapLoader * _ref ) : - m_name( _ref != NULL ? _ref->m_name : QString::null ) + m_name( _ref != NULL ? _ref->m_name : QString() ), + m_xpm( _ref->m_xpm ) { } - PixmapLoader( const QString & _name = QString::null ) : - m_name( _name ) + PixmapLoader( const QString & _name = QString(), + const char** xpm = nullptr ) : + m_name( _name ), + m_xpm(xpm) { } @@ -73,7 +87,8 @@ public: { if( !m_name.isEmpty() ) { - return( embed::getIconPixmap( m_name.toLatin1().constData() ) ); + return( embed::getIconPixmap( + m_name.toLatin1().constData(), -1, -1, m_xpm )); } return( QPixmap() ); } @@ -89,6 +104,7 @@ public: protected: QString m_name; + const char** m_xpm = nullptr; } ; @@ -96,7 +112,7 @@ protected: class PluginPixmapLoader : public PixmapLoader { public: - PluginPixmapLoader( const QString & _name = QString::null ) : + PluginPixmapLoader( const QString & _name = QString() ) : PixmapLoader( _name ) { } diff --git a/include/fft_helpers.h b/include/fft_helpers.h index c28af0237..876510f8b 100644 --- a/include/fft_helpers.h +++ b/include/fft_helpers.h @@ -2,6 +2,7 @@ * fft_helpers.h - some functions around FFT analysis * * Copyright (c) 2008-2012 Tobias Doerffel + * Copyright (c) 2019 Martin Pavelek * * This file is part of LMMS - https://lmms.io * @@ -26,59 +27,92 @@ #ifndef FFT_HELPERS_H #define FFT_HELPERS_H -#include "export.h" +#include "lmms_export.h" +#include #include -const int FFT_BUFFER_SIZE = 2048; +// NOTE: FFT_BUFFER_SIZE should be considered deprecated! +// It is used by Eq plugin and some older code here, but this should be a user +// switchable parameter, not a constant. Use a value from FFT_BLOCK_SIZES +const unsigned int FFT_BUFFER_SIZE = 2048; -enum WINDOWS +// Allowed FFT block sizes. Ranging from barely useful to barely acceptable +// because of performance and latency reasons. +const std::vector FFT_BLOCK_SIZES = {256, 512, 1024, 2048, 4096, 8192, 16384}; + +// List of FFT window functions supported by precomputeWindow() +enum FFT_WINDOWS { - KAISER=1, - RECTANGLE, - HANNING, - HAMMING + RECTANGULAR = 0, + BLACKMAN_HARRIS, + HAMMING, + HANNING }; -/* returns biggest value from abs_spectrum[spec_size] array + +/** Returns biggest value from abs_spectrum[spec_size] array. * - * returns -1 on error + * @return -1 on error, 0 on success */ -float EXPORT maximum( float * _abs_spectrum, unsigned int _spec_size ); +float LMMS_EXPORT maximum(const float *abs_spectrum, unsigned int spec_size); +float LMMS_EXPORT maximum(const std::vector &abs_spectrum); -/* apply hanning or hamming window to channel + +/** Normalize the abs_spectrum array of absolute values to a 0..1 range + * based on supplied energy and stores it in the norm_spectrum array. * - * returns -1 on error + * @return -1 on error */ -int EXPORT hanming( float * _timebuffer, int _length, WINDOWS _type ); +int LMMS_EXPORT normalize(const float *abs_spectrum, float *norm_spectrum, unsigned int bin_count, unsigned int block_size); +int LMMS_EXPORT normalize(const std::vector &abs_spectrum, std::vector &norm_spectrum, unsigned int block_size); -/* compute absolute values of complex_buffer, save to absspec_buffer - * take care that - compl_len is not bigger than complex_buffer! - * - absspec buffer is big enough! + +/** Check if the spectrum contains any non-zero value. * - * returns 0 on success, else -1 + * @return 1 if spectrum contains any non-zero value + * @return 0 otherwise */ -int EXPORT absspec( fftwf_complex * _complex_buffer, float * _absspec_buffer, - int _compl_length ); +int LMMS_EXPORT notEmpty(const std::vector &spectrum); -/* build fewer subbands from many absolute spectrum values - * take care that - compressedbands[] array num_new elements long - * - num_old > num_new + +/** Precompute a window function for later real-time use. + * Set normalized to false if you do not want to apply amplitude correction. * - * returns 0 on success, else -1 + * @return -1 on error */ -int EXPORT compressbands( float * _absspec_buffer, float * _compressedband, - int _num_old, int _num_new, int _bottom, int _top ); +int LMMS_EXPORT precomputeWindow(float *window, unsigned int length, FFT_WINDOWS type, bool normalized = true); -int EXPORT calc13octaveband31( float * _absspec_buffer, float * _subbands, - int _num_spec, float _max_frequency ); - -/* compute power of finite time sequence - * take care num_values is length of timesignal[] +/** Compute absolute values of complex_buffer, save to absspec_buffer. + * Take care that - compl_len is not bigger than complex_buffer! + * - absspec buffer is big enough! * - * returns power on success, else -1 + * @return 0 on success, else -1 */ -float EXPORT signalpower(float *timesignal, int num_values); +int LMMS_EXPORT absspec(const fftwf_complex *complex_buffer, float *absspec_buffer, + unsigned int compl_length); + + +/** Build fewer subbands from many absolute spectrum values. + * Take care that - compressedbands[] array num_new elements long + * - num_old > num_new + * + * @return 0 on success, else -1 + */ +int LMMS_EXPORT compressbands(const float * _absspec_buffer, float * _compressedband, + int _num_old, int _num_new, int _bottom, int _top); + + +int LMMS_EXPORT calc13octaveband31(float * _absspec_buffer, float * _subbands, + int _num_spec, float _max_frequency); + + +/** Compute power of finite time sequence. + * Take care num_values is length of timesignal[]. + * + * @return power on success, else -1 + */ +float LMMS_EXPORT signalpower(const float *timesignal, int num_values); #endif diff --git a/include/fifo_buffer.h b/include/fifo_buffer.h index 39f9867fe..422b48df2 100644 --- a/include/fifo_buffer.h +++ b/include/fifo_buffer.h @@ -66,6 +66,12 @@ public: return( element ); } + void waitUntilRead() + { + m_writer_sem.acquire( m_size ); + m_writer_sem.release( m_size ); + } + bool available() { return( m_reader_sem.available() ); diff --git a/include/lmms_basics.h b/include/lmms_basics.h index 637867b4d..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; @@ -141,5 +141,11 @@ typedef sample_t sampleFrameA[DEFAULT_CHANNELS] __attribute__((__aligned__(ALIGN #define STRINGIFY(s) STR(s) #define STR(PN) #PN +// Abstract away GUI CTRL key (linux/windows) vs ⌘ (apple) +#ifdef LMMS_BUILD_APPLE +# define UI_CTRL_KEY "⌘" +#else +# define UI_CTRL_KEY "Ctrl" +#endif #endif diff --git a/include/panning.h b/include/panning.h index 5f10433ce..c043adf5c 100644 --- a/include/panning.h +++ b/include/panning.h @@ -27,10 +27,9 @@ #define PANNING_H #include "lmms_basics.h" -#include "volume.h" -#include "templates.h" #include "panning_constants.h" #include "Midi.h" +#include "volume.h" inline stereoVolumeVector panningToVolumeVector( panning_t _p, float _scale = 1.0f ) diff --git a/include/stdshims.h b/include/stdshims.h index 456d31607..85c4f457a 100644 --- a/include/stdshims.h +++ b/include/stdshims.h @@ -7,8 +7,10 @@ #include #include -#if (__cplusplus >= 201402L) +#if (__cplusplus >= 201402L || _MSC_VER) +#ifndef _MSC_VER #warning "This file should now be removed! The functions it provides are part of the C++14 standard." +#endif using std::make_unique; #else diff --git a/include/templates.h b/include/templates.h deleted file mode 100644 index 50a14a6b8..000000000 --- a/include/templates.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * templates.h - miscellanous templates and algorithms - * - * Copyright (c) 2004-2008 Tobias Doerffel - * - * 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 TEMPLATES_H -#define TEMPLATES_H - -#include - - -template -inline T tLimit( const T x, const T x1, const T x2 ) -{ - return qBound( x1, x, x2 ); -} - - -#endif diff --git a/include/versioninfo.h b/include/versioninfo.h index b34936d57..a5d3d64c6 100644 --- a/include/versioninfo.h +++ b/include/versioninfo.h @@ -32,6 +32,10 @@ #define PLATFORM "OpenBSD" #endif +#ifdef LMMS_BUILD_FREEBSD +#define PLATFORM "FreeBSD" +#endif + #ifdef LMMS_BUILD_WIN32 #define PLATFORM "win32" #endif diff --git a/include/volume.h b/include/volume.h index f0f7708ad..9172395d6 100644 --- a/include/volume.h +++ b/include/volume.h @@ -26,10 +26,7 @@ #ifndef VOLUME_H #define VOLUME_H -#include "lmmsconfig.h" - #include "lmms_basics.h" -#include "Midi.h" const volume_t MinVolume = 0; const volume_t MaxVolume = 200; diff --git a/plugins/Amplifier/Amplifier.cpp b/plugins/Amplifier/Amplifier.cpp index c11fa6bcc..d90ea55b3 100644 --- a/plugins/Amplifier/Amplifier.cpp +++ b/plugins/Amplifier/Amplifier.cpp @@ -26,7 +26,7 @@ #include "Amplifier.h" #include "embed.h" - +#include "plugin_export.h" extern "C" { diff --git a/plugins/BassBooster/BassBooster.cpp b/plugins/BassBooster/BassBooster.cpp index f7387b46e..6fdb1671c 100644 --- a/plugins/BassBooster/BassBooster.cpp +++ b/plugins/BassBooster/BassBooster.cpp @@ -25,7 +25,7 @@ #include "BassBooster.h" #include "embed.h" - +#include "plugin_export.h" extern "C" { diff --git a/plugins/Bitcrush/Bitcrush.cpp b/plugins/Bitcrush/Bitcrush.cpp index 918b8efdd..0580d47cd 100644 --- a/plugins/Bitcrush/Bitcrush.cpp +++ b/plugins/Bitcrush/Bitcrush.cpp @@ -25,6 +25,7 @@ #include "Bitcrush.h" #include "embed.h" +#include "plugin_export.h" const int OS_RATE = 5; const float OS_RATIO = 1.0f / OS_RATE; diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index cb36db03f..a4e56921f 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -1,5 +1,5 @@ -SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) -SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) +SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") +SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") SET(CMAKE_DEBUG_POSTFIX "") # Enable C++11 @@ -11,100 +11,10 @@ ENDIF() INCLUDE_DIRECTORIES( ${SAMPLERATE_INCLUDE_DIRS} + "${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 - vestige - vst_base - VstEffect - watsyn - waveshaper - vibed - Xpressive - zynaddsubfx - ) - -ENDIF("${PLUGIN_LIST}" STREQUAL "") - -IF(MSVC) - SET(MSVC_INCOMPATIBLE_PLUGINS - LadspaEffect - monstro - organic - ReverbSC - sid - vestige - vibed - vst_base - VstEffect - Xpressive - zynaddsubfx - ) - message(WARNING "Compiling with MSVC. The following plugins are not available: ${MSVC_INCOMPATIBLE_PLUGINS}") - LIST(REMOVE_ITEM PLUGIN_LIST ${MSVC_INCOMPATIBLE_PLUGINS}) -ENDIF() - +# See cmake/modules/PluginList.cmake FOREACH(PLUGIN ${PLUGIN_LIST}) ADD_SUBDIRECTORY(${PLUGIN}) ENDFOREACH() diff --git a/plugins/CrossoverEQ/CrossoverEQ.cpp b/plugins/CrossoverEQ/CrossoverEQ.cpp index 3dc0e8265..e7d3dce7d 100644 --- a/plugins/CrossoverEQ/CrossoverEQ.cpp +++ b/plugins/CrossoverEQ/CrossoverEQ.cpp @@ -27,6 +27,7 @@ #include "CrossoverEQ.h" #include "lmms_math.h" #include "embed.h" +#include "plugin_export.h" extern "C" { diff --git a/plugins/Delay/DelayEffect.cpp b/plugins/Delay/DelayEffect.cpp index 0161178b8..0daad0d9d 100644 --- a/plugins/Delay/DelayEffect.cpp +++ b/plugins/Delay/DelayEffect.cpp @@ -26,7 +26,7 @@ #include "Engine.h" #include "embed.h" #include "interpolation.h" - +#include "plugin_export.h" extern "C" { diff --git a/plugins/DualFilter/DualFilter.cpp b/plugins/DualFilter/DualFilter.cpp index 94450cc6f..5b8b7a622 100644 --- a/plugins/DualFilter/DualFilter.cpp +++ b/plugins/DualFilter/DualFilter.cpp @@ -27,7 +27,7 @@ #include "embed.h" #include "BasicFilters.h" - +#include "plugin_export.h" extern "C" { diff --git a/plugins/Eq/CMakeLists.txt b/plugins/Eq/CMakeLists.txt index 36109cb3c..899dde5ec 100644 --- a/plugins/Eq/CMakeLists.txt +++ b/plugins/Eq/CMakeLists.txt @@ -1,6 +1,5 @@ INCLUDE(BuildPlugin) INCLUDE_DIRECTORIES(${FFTW3F_INCLUDE_DIRS}) -LINK_DIRECTORIES(${FFTW3F_LIBRARY_DIRS}) LINK_LIBRARIES(${FFTW3F_LIBRARIES}) BUILD_PLUGIN(eq EqEffect.cpp EqCurve.cpp EqCurve.h EqControls.cpp EqControlsDialog.cpp EqFilter.h EqParameterWidget.cpp EqFader.h EqSpectrumView.h EqSpectrumView.cpp MOCFILES EqControls.h EqControlsDialog.h EqCurve.h EqParameterWidget.h EqFader.h EqSpectrumView.h EMBEDDED_RESOURCES *.png) diff --git a/plugins/Eq/EqControlsDialog.cpp b/plugins/Eq/EqControlsDialog.cpp index af2378a2c..00c8eaaa7 100644 --- a/plugins/Eq/EqControlsDialog.cpp +++ b/plugins/Eq/EqControlsDialog.cpp @@ -55,10 +55,10 @@ EqControlsDialog::EqControlsDialog( EqControls *controls ) : EqSpectrumView * inSpec = new EqSpectrumView( &controls->m_inFftBands, this ); inSpec->move( 26, 17 ); - inSpec->setColor( QColor( 54, 45, 142, 150 ) ); + inSpec->setColor( QColor( 77, 101, 242, 150 ) ); EqSpectrumView * outSpec = new EqSpectrumView( &controls->m_outFftBands, this ); - outSpec->setColor( QColor( 9, 166, 156, 150 ) ); + outSpec->setColor( QColor( 0, 255, 239, 150 ) ); outSpec->move( 26, 17 ); m_parameterWidget = new EqParameterWidget( this , controls ); diff --git a/plugins/Eq/EqEffect.cpp b/plugins/Eq/EqEffect.cpp index 64b43e5a5..6b7c61bcc 100644 --- a/plugins/Eq/EqEffect.cpp +++ b/plugins/Eq/EqEffect.cpp @@ -24,12 +24,13 @@ #include "EqEffect.h" -#include "embed.h" #include "Engine.h" #include "EqFader.h" #include "interpolation.h" #include "lmms_math.h" +#include "embed.h" +#include "plugin_export.h" extern "C" { diff --git a/plugins/Eq/EqFader.h b/plugins/Eq/EqFader.h index 6f9b26615..c588c2b92 100644 --- a/plugins/Eq/EqFader.h +++ b/plugins/Eq/EqFader.h @@ -80,7 +80,7 @@ private slots: { const float opl = getPeak_L(); const float opr = getPeak_R(); - const float fall_off = 1.2; + const float fallOff = 1.07; if( *m_lPeak > opl ) { setPeak_L( *m_lPeak ); @@ -88,7 +88,7 @@ private slots: } else { - setPeak_L( opl/fall_off ); + setPeak_L( opl/fallOff ); } if( *m_rPeak > opr ) @@ -98,7 +98,7 @@ private slots: } else { - setPeak_R( opr/fall_off ); + setPeak_R( opr/fallOff ); } update(); } diff --git a/plugins/Eq/EqSpectrumView.cpp b/plugins/Eq/EqSpectrumView.cpp index 79bf5b04a..e9e0043de 100644 --- a/plugins/Eq/EqSpectrumView.cpp +++ b/plugins/Eq/EqSpectrumView.cpp @@ -45,11 +45,11 @@ EqAnalyser::EqAnalyser() : const float a2 = 0.14128; const float a3 = 0.01168; - for(int i = 0; i < FFT_BUFFER_SIZE; i++) + for (int i = 0; i < FFT_BUFFER_SIZE; i++) { - m_fftWindow[i] = ( a0 - a1 * cosf( 2 * F_PI * i / (float)FFT_BUFFER_SIZE - 1 ) - + a2 * cosf( 4 * F_PI * i / (float)FFT_BUFFER_SIZE-1) - - a3 * cos( 6 * F_PI * i / (float)FFT_BUFFER_SIZE - 1.0 )); + m_fftWindow[i] = (a0 - a1 * cos(2 * F_PI * i / ((float)FFT_BUFFER_SIZE - 1.0)) + + a2 * cos(4 * F_PI * i / ((float)FFT_BUFFER_SIZE - 1.0)) + - a3 * cos(6 * F_PI * i / ((float)FFT_BUFFER_SIZE - 1.0))); } clear(); } @@ -223,7 +223,7 @@ void EqSpectrumView::paintEvent(QPaintEvent *event) float peak; m_path.moveTo( 0, height() ); m_peakSum = 0; - float fallOff = 1.2; + const float fallOff = 1.07; for( int x = 0; x < MAX_BANDS; ++x, ++bands ) { peak = ( fh * 2.0 / 3.0 * ( 20 * ( log10( *bands / energy ) ) - LOWER_Y ) / ( - LOWER_Y ) ); diff --git a/plugins/Flanger/FlangerEffect.cpp b/plugins/Flanger/FlangerEffect.cpp index 1404c06b0..7e441cf62 100644 --- a/plugins/Flanger/FlangerEffect.cpp +++ b/plugins/Flanger/FlangerEffect.cpp @@ -24,7 +24,9 @@ #include "FlangerEffect.h" #include "Engine.h" + #include "embed.h" +#include "plugin_export.h" extern "C" { diff --git a/plugins/FreeBoy/FreeBoy.cpp b/plugins/FreeBoy/FreeBoy.cpp index 75391e452..2f787044f 100644 --- a/plugins/FreeBoy/FreeBoy.cpp +++ b/plugins/FreeBoy/FreeBoy.cpp @@ -42,6 +42,8 @@ #include "embed.h" +#include "plugin_export.h" + const blip_time_t FRAME_LENGTH = 70224; const long CLOCK_RATE = 4194304; @@ -107,11 +109,11 @@ FreeBoyInstrument::FreeBoyInstrument( InstrumentTrack * _instrument_track ) : m_ch1So1Model( true, this, tr( "Channel 1 to SO2 (Left)" ) ), m_ch2So1Model( true, this, tr( "Channel 2 to SO2 (Left)" ) ), m_ch3So1Model( true, this, tr( "Channel 3 to SO2 (Left)" ) ), - m_ch4So1Model( true, this, tr( "Channel 4 to SO2 (Left)" ) ), + m_ch4So1Model( false, this, tr( "Channel 4 to SO2 (Left)" ) ), m_ch1So2Model( true, this, tr( "Channel 1 to SO1 (Right)" ) ), m_ch2So2Model( true, this, tr( "Channel 2 to SO1 (Right)" ) ), m_ch3So2Model( true, this, tr( "Channel 3 to SO1 (Right)" ) ), - m_ch4So2Model( true, this, tr( "Channel 4 to SO1 (Right)" ) ), + m_ch4So2Model( false, this, tr( "Channel 4 to SO1 (Right)" ) ), m_trebleModel( -20.0f, -100.0f, 200.0f, 1.0f, this, tr( "Treble" ) ), m_bassModel( 461.0f, -1.0f, 600.0f, 1.0f, this, tr( "Bass" ) ), @@ -281,9 +283,6 @@ void FreeBoyInstrument::playNote( NotePlayHandle * _n, data += m_ch4SweepStepLengthModel.value(); papu->write_register( fakeClock(), 0xff21, data ); - //channel 4 init - papu->write_register( fakeClock(), 0xff23, 128 ); - _n->m_pluginData = papu; } @@ -385,6 +384,9 @@ void FreeBoyInstrument::playNote( NotePlayHandle * _n, data = data << 3; data += ropt; papu->write_register( fakeClock(), 0xff22, data ); + + //channel 4 init + papu->write_register( fakeClock(), 0xff23, 128 ); } int const buf_size = 2048; @@ -455,7 +457,7 @@ public: FreeBoyInstrumentView::FreeBoyInstrumentView( Instrument * _instrument, QWidget * _parent ) : - InstrumentView( _instrument, _parent ) + InstrumentViewFixedSize( _instrument, _parent ) { setAutoFillBackground( true ); @@ -726,10 +728,10 @@ extern "C" { // necessary for getting instance out of shared lib -PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *, void * _data ) +PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *m, void * ) { return( new FreeBoyInstrument( - static_cast( _data ) ) ); + static_cast( m ) ) ); } diff --git a/plugins/FreeBoy/FreeBoy.h b/plugins/FreeBoy/FreeBoy.h index 69c478505..9ceb27966 100644 --- a/plugins/FreeBoy/FreeBoy.h +++ b/plugins/FreeBoy/FreeBoy.h @@ -111,7 +111,7 @@ private: } ; -class FreeBoyInstrumentView : public InstrumentView +class FreeBoyInstrumentView : public InstrumentViewFixedSize { Q_OBJECT public: diff --git a/plugins/GigPlayer/GigPlayer.cpp b/plugins/GigPlayer/GigPlayer.cpp index 938cd10b1..b358e24e9 100644 --- a/plugins/GigPlayer/GigPlayer.cpp +++ b/plugins/GigPlayer/GigPlayer.cpp @@ -53,7 +53,7 @@ #include "LcdSpinBox.h" #include "embed.h" - +#include "plugin_export.h" extern "C" { @@ -922,7 +922,7 @@ public: GigInstrumentView::GigInstrumentView( Instrument * _instrument, QWidget * _parent ) : - InstrumentView( _instrument, _parent ) + InstrumentViewFixedSize( _instrument, _parent ) { GigInstrument * k = castModel(); @@ -1390,9 +1390,9 @@ extern "C" { // necessary for getting instance out of shared lib -Plugin * PLUGIN_EXPORT lmms_plugin_main( Model *, void * _data ) +PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *m, void * ) { - return new GigInstrument( static_cast( _data ) ); + return new GigInstrument( static_cast( m ) ); } } diff --git a/plugins/GigPlayer/GigPlayer.h b/plugins/GigPlayer/GigPlayer.h index 0a5e023f9..b9467b91b 100644 --- a/plugins/GigPlayer/GigPlayer.h +++ b/plugins/GigPlayer/GigPlayer.h @@ -334,7 +334,7 @@ signals: -class GigInstrumentView : public InstrumentView +class GigInstrumentView : public InstrumentViewFixedSize { Q_OBJECT public: diff --git a/plugins/GigPlayer/PatchesDialog.cpp b/plugins/GigPlayer/PatchesDialog.cpp index ac7c4d330..7be3bfd98 100644 --- a/plugins/GigPlayer/PatchesDialog.cpp +++ b/plugins/GigPlayer/PatchesDialog.cpp @@ -74,11 +74,7 @@ PatchesDialog::PatchesDialog( QWidget * pParent, Qt::WindowFlags wflags ) // Soundfonts list view... QHeaderView * pHeader = m_progListView->header(); pHeader->setDefaultAlignment( Qt::AlignLeft ); -#if QT_VERSION >= 0x050000 pHeader->setSectionsMovable( false ); -#else - pHeader->setMovable( false ); -#endif pHeader->setStretchLastSection( true ); m_progListView->resizeColumnToContents( 0 ); // Prog. diff --git a/plugins/HydrogenImport/HydrogenImport.cpp b/plugins/HydrogenImport/HydrogenImport.cpp index c7536e87e..9f9f1dd49 100644 --- a/plugins/HydrogenImport/HydrogenImport.cpp +++ b/plugins/HydrogenImport/HydrogenImport.cpp @@ -19,6 +19,8 @@ #include "BBTrackContainer.h" #include "Instrument.h" +#include "plugin_export.h" + #define MAX_LAYERS 4 extern "C" { diff --git a/plugins/LadspaEffect/LadspaControls.cpp b/plugins/LadspaEffect/LadspaControls.cpp index 1a2f26a35..028394d30 100644 --- a/plugins/LadspaEffect/LadspaControls.cpp +++ b/plugins/LadspaEffect/LadspaControls.cpp @@ -36,7 +36,8 @@ LadspaControls::LadspaControls( LadspaEffect * _eff ) : { connect( &m_stereoLinkModel, SIGNAL( dataChanged() ), - this, SLOT( updateLinkStatesFromGlobal() ) ); + this, SLOT( updateLinkStatesFromGlobal() ), + Qt::DirectConnection ); multi_proc_t controls = m_effect->getPortControls(); m_controlCount = controls.count(); @@ -59,7 +60,8 @@ LadspaControls::LadspaControls( LadspaEffect * _eff ) : if( linked_control ) { connect( (*it)->control, SIGNAL( linkChanged( int, bool ) ), - this, SLOT( linkPort( int, bool ) ) ); + this, SLOT( linkPort( int, bool ) ), + Qt::DirectConnection ); } } } @@ -153,6 +155,9 @@ void LadspaControls::linkPort( int _port, bool _state ) { first->unlinkControls( m_controls[proc][_port] ); } + + // m_stereoLinkModel.setValue() will call updateLinkStatesFromGlobal() + // m_noLink will make sure that this will not unlink any other ports m_noLink = true; m_stereoLinkModel.setValue( false ); } diff --git a/plugins/LadspaEffect/LadspaEffect.cpp b/plugins/LadspaEffect/LadspaEffect.cpp index aceea2d41..d7e66bf47 100644 --- a/plugins/LadspaEffect/LadspaEffect.cpp +++ b/plugins/LadspaEffect/LadspaEffect.cpp @@ -44,6 +44,7 @@ #include "embed.h" +#include "plugin_export.h" extern "C" { @@ -122,9 +123,6 @@ void LadspaEffect::changeSampleRate() // the IDs of re-created controls have been saved and now need to be // resolved again AutomationPattern::resolveAllIDs(); - - // make sure, connections are ok - ControllerConnection::finalizeConnections(); } diff --git a/plugins/LadspaEffect/LadspaSubPluginFeatures.cpp b/plugins/LadspaEffect/LadspaSubPluginFeatures.cpp index e9344e943..4cefa90b5 100644 --- a/plugins/LadspaEffect/LadspaSubPluginFeatures.cpp +++ b/plugins/LadspaEffect/LadspaSubPluginFeatures.cpp @@ -44,6 +44,16 @@ LadspaSubPluginFeatures::LadspaSubPluginFeatures( Plugin::PluginTypes _type ) : +QString LadspaSubPluginFeatures::displayName(const Plugin::Descriptor::SubPluginFeatures::Key &k) const +{ + const ladspa_key_t & lkey = subPluginKeyToLadspaKey(&k); + Ladspa2LMMS * lm = Engine::getLADSPAManager(); + return lm->getName(lkey); +} + + + + void LadspaSubPluginFeatures::fillDescriptionWidget( QWidget * _parent, const Key * _key ) const { diff --git a/plugins/LadspaEffect/LadspaSubPluginFeatures.h b/plugins/LadspaEffect/LadspaSubPluginFeatures.h index 904c8133b..3f47734f9 100644 --- a/plugins/LadspaEffect/LadspaSubPluginFeatures.h +++ b/plugins/LadspaEffect/LadspaSubPluginFeatures.h @@ -25,8 +25,8 @@ * */ -#ifndef _LADSPA_SUBPLUGIN_FEATURES_H -#define _LADSPA_SUBPLUGIN_FEATURES_H +#ifndef LADSPA_SUBPLUGIN_FEATURES_H +#define LADSPA_SUBPLUGIN_FEATURES_H #include "LadspaManager.h" #include "Plugin.h" @@ -37,11 +37,13 @@ class LadspaSubPluginFeatures : public Plugin::Descriptor::SubPluginFeatures public: LadspaSubPluginFeatures( Plugin::PluginTypes _type ); - virtual void fillDescriptionWidget( QWidget * _parent, - const Key * _key ) const; + QString displayName(const Key& k) const override; + void fillDescriptionWidget( QWidget * _parent, + const Key * _key ) const override; virtual void listSubPluginKeys( const Plugin::Descriptor * _desc, - KeyList & _kl ) const; + KeyList & _kl ) const override; + static ladspa_key_t subPluginKeyToLadspaKey( const Key * _key ); diff --git a/plugins/LadspaEffect/calf/CMakeLists.txt b/plugins/LadspaEffect/calf/CMakeLists.txt index 776752bc5..4924169e4 100644 --- a/plugins/LadspaEffect/calf/CMakeLists.txt +++ b/plugins/LadspaEffect/calf/CMakeLists.txt @@ -16,8 +16,9 @@ LIST(SORT SOURCES) # Skip files matching pattern SET(FILE_PATTERNS "ctl;gui;gtk;session;connector;jack;rdf;draw;fluid;preset;lv2;benchmark;win;plugin.cpp") FOREACH(_item ${SOURCES}) + GET_FILENAME_COMPONENT(m_basename ${_item} NAME) FOREACH(_pattern ${FILE_PATTERNS}) - IF(${_item} MATCHES ${_pattern}) + IF(${m_basename} MATCHES ${_pattern}) LIST(REMOVE_ITEM SOURCES ${_item}) ENDIF() ENDFOREACH() diff --git a/plugins/LadspaEffect/swh/CMakeLists.txt b/plugins/LadspaEffect/swh/CMakeLists.txt index fb8b03400..131e60373 100644 --- a/plugins/LadspaEffect/swh/CMakeLists.txt +++ b/plugins/LadspaEffect/swh/CMakeLists.txt @@ -8,13 +8,6 @@ ELSE() SET(PIC_FLAGS "-fPIC -DPIC") ENDIF() -# Additional link flags -IF(LMMS_BUILD_WIN32 AND MINGW_PREFIX) - SET(LINK_FLAGS "${LINK_FLAGS} -shared -Wl,-no-undefined -Wl,-Bsymbolic -lm") -ELSEIF(LMMS_BUILD_APPLE) - SET(LINK_FLAGS "${LINK_FLAGS} -Bsymbolic -lm") -ENDIF() - # Additional compile flags SET(COMPILE_FLAGS "${COMPILE_FLAGS} -O3 -Wall") SET(COMPILE_FLAGS "${COMPILE_FLAGS} -fomit-frame-pointer -funroll-loops -ffast-math -c -fno-strict-aliasing") @@ -42,7 +35,10 @@ FOREACH(_item ${XML_SOURCES}) # Vocoder does not use fftw IF(NOT ("${_plugin}" STREQUAL "vocoder_1337")) - TARGET_LINK_LIBRARIES("${_plugin}" -lfftw3f) + TARGET_LINK_LIBRARIES("${_plugin}" ${FFTW3F_LIBRARIES}) + ENDIF() + IF(NOT MSVC) + TARGET_LINK_LIBRARIES("${_plugin}" m) ENDIF() SET_TARGET_PROPERTIES("${_plugin}" PROPERTIES PREFIX "") @@ -55,10 +51,9 @@ ADD_DEFINITIONS(-DFFTW3) INCLUDE_DIRECTORIES( "${CMAKE_SOURCE_DIR}/include" "${CMAKE_CURRENT_SOURCE_DIR}/ladspa" - ${FFTW3F_INCLUDE_DIRS} + "${FFTW3F_INCLUDE_DIRS}" "${CMAKE_BINARY_DIR}" ) -LINK_DIRECTORIES(${FFTW3F_LIBRARY_DIRS}) ADD_LIBRARY(iir STATIC ladspa/util/iir.c) SET_TARGET_PROPERTIES(iir PROPERTIES COMPILE_FLAGS "${PIC_FLAGS}") diff --git a/plugins/LadspaEffect/tap/CMakeLists.txt b/plugins/LadspaEffect/tap/CMakeLists.txt index 0ae8ae54e..e0740bd5e 100644 --- a/plugins/LadspaEffect/tap/CMakeLists.txt +++ b/plugins/LadspaEffect/tap/CMakeLists.txt @@ -15,13 +15,8 @@ FOREACH(_item ${PLUGIN_SOURCES}) IF(LMMS_BUILD_WIN32 AND NOT CMAKE_BUILD_TYPE MATCHES "Deb") ADD_CUSTOM_COMMAND(TARGET "${_plugin}" POST_BUILD COMMAND "${STRIP}" \"$\") ENDIF() - IF(LMMS_BUILD_APPLE) - SET_TARGET_PROPERTIES("${_plugin}" PROPERTIES LINK_FLAGS "${LINK_FLAGS} -Bsymbolic -lm") - ELSEIF(NOT LMMS_BUILD_OPENBSD) - SET_TARGET_PROPERTIES("${_plugin}" PROPERTIES LINK_FLAGS "${LINK_FLAGS} -shared -Wl,-no-undefined -Wl,-Bsymbolic -lm") - ENDIF() - IF(LMMS_BUILD_LINUX OR LMMS_BUILD_HAIKU) - SET_TARGET_PROPERTIES("${_plugin}" PROPERTIES LINK_FLAGS "${LINK_FLAGS}") + IF(NOT MSVC) + TARGET_LINK_LIBRARIES("${_plugin}" m) ENDIF() ENDFOREACH() diff --git a/plugins/MidiExport/MidiExport.cpp b/plugins/MidiExport/MidiExport.cpp index d691c4830..1860527c1 100644 --- a/plugins/MidiExport/MidiExport.cpp +++ b/plugins/MidiExport/MidiExport.cpp @@ -36,7 +36,9 @@ #include "TrackContainer.h" #include "BBTrack.h" #include "InstrumentTrack.h" +#include "LocaleHelper.h" +#include "plugin_export.h" extern "C" { @@ -133,7 +135,7 @@ bool MidiExport::tryExport(const TrackContainer::TrackList &tracks, { base_pitch += masterPitch; } - base_volume = it.attribute("volume", "100").toDouble()/100.0; + base_volume = LocaleHelper::toDouble(it.attribute("volume", "100"))/100.0; } if (n.nodeName() == "pattern") @@ -204,7 +206,7 @@ bool MidiExport::tryExport(const TrackContainer::TrackList &tracks, { base_pitch += masterPitch; } - base_volume = it.attribute("volume", "100").toDouble() / 100.0; + base_volume = LocaleHelper::toDouble(it.attribute("volume", "100")) / 100.0; } if (n.nodeName() == "pattern") @@ -273,7 +275,8 @@ void MidiExport::writePattern(MidiNoteVector &pat, QDomNode n, // TODO interpret pan="0" fxch="0" pitchrange="1" MidiNote mnote; mnote.pitch = qMax(0, qMin(127, note.attribute("key", "0").toInt() + base_pitch)); - mnote.volume = qMin(qRound(base_volume * note.attribute("vol", "100").toDouble()), 127); + // Map from LMMS volume to MIDI velocity + mnote.volume = qMin(qRound(base_volume * LocaleHelper::toDouble(note.attribute("vol", "100")) * (127.0 / 200.0)), 127); mnote.time = base_time + note.attribute("pos", "0").toInt(); mnote.duration = note.attribute("len", "0").toInt(); pat.push_back(mnote); diff --git a/plugins/MidiImport/MidiImport.cpp b/plugins/MidiImport/MidiImport.cpp index 729c8b200..b3d01e790 100644 --- a/plugins/MidiImport/MidiImport.cpp +++ b/plugins/MidiImport/MidiImport.cpp @@ -26,9 +26,12 @@ #include #include #include +#include #include #include +#include + #include "MidiImport.h" #include "TrackContainer.h" #include "InstrumentTrack.h" @@ -41,9 +44,11 @@ #include "MainWindow.h" #include "MidiTime.h" #include "debug.h" -#include "embed.h" #include "Song.h" +#include "embed.h" +#include "plugin_export.h" + #include "portsmf/allegro.h" #define makeID(_c0, _c1, _c2, _c3) \ @@ -98,11 +103,11 @@ 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" ), - tr( "You do not have set up a default soundfont in " + tr( "You have not set up a default soundfont in " "the settings dialog (Edit->Settings). " "Therefore no sound will be played back after " "importing this MIDI file. You should download " @@ -183,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 ); @@ -195,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; } @@ -237,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 ); } @@ -262,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 ); } @@ -279,8 +284,6 @@ public: bool MidiImport::readSMF( TrackContainer* tc ) { - QString filename = file().fileName(); - closeFile(); const int preTrackSteps = 2; QProgressDialog pd( TrackContainer::tr( "Importing MIDI-file..." ), @@ -291,7 +294,11 @@ bool MidiImport::readSMF( TrackContainer* tc ) pd.setValue( 0 ); - Alg_seq_ptr seq = new Alg_seq(filename.toLocal8Bit(), true); + std::stringstream stream; + QByteArray arr = readAllData(); + stream.str(std::string(arr.constData(), arr.size())); + + Alg_seq_ptr seq = new Alg_seq(stream, true); seq->convert_to_beats(); pd.setMaximum( seq->tracks() + preTrackSteps ); @@ -302,33 +309,36 @@ bool MidiImport::readSMF( TrackContainer* tc ) smfMidiChannel chs[256]; MeterModel & timeSigMM = Engine::getSong()->getTimeSigModel(); - AutomationPattern * timeSigNumeratorPat = - AutomationPattern::globalAutomationPattern( &timeSigMM.numeratorModel() ); - AutomationPattern * timeSigDenominatorPat = - AutomationPattern::globalAutomationPattern( &timeSigMM.denominatorModel() ); + AutomationTrack * nt = dynamic_cast( + Track::create(Track::AutomationTrack, Engine::getSong())); + nt->setName(tr("MIDI Time Signature Numerator")); + AutomationTrack * dt = dynamic_cast( + Track::create(Track::AutomationTrack, Engine::getSong())); + dt->setName(tr("MIDI Time Signature Denominator")); + AutomationPattern * timeSigNumeratorPat = + new AutomationPattern(nt); + timeSigNumeratorPat->setDisplayName(tr("Numerator")); + timeSigNumeratorPat->addObject(&timeSigMM.numeratorModel()); + AutomationPattern * timeSigDenominatorPat = + new AutomationPattern(dt); + timeSigDenominatorPat->setDisplayName(tr("Denominator")); + timeSigDenominatorPat->addObject(&timeSigMM.denominatorModel()); // TODO: adjust these to Time.Sig changes - double beatsPerTact = 4; - double ticksPerBeat = DefaultTicksPerTact / beatsPerTact; + double beatsPerBar = 4; + double ticksPerBeat = DefaultTicksPerBar / beatsPerBar; // Time-sig changes Alg_time_sigs * timeSigs = &seq->time_sig; for( int s = 0; s < timeSigs->length(); ++s ) { Alg_time_sig timeSig = (*timeSigs)[s]; - // Initial timeSig, set song-default value - if(/* timeSig.beat == 0*/ true ) - { - // TODO set song-global default value - printf("Another timesig at %f\n", timeSig.beat); - timeSigNumeratorPat->putValue( timeSig.beat*ticksPerBeat, timeSig.num ); - timeSigDenominatorPat->putValue( timeSig.beat*ticksPerBeat, timeSig.den ); - } - else - { - } - + timeSigNumeratorPat->putValue(timeSig.beat * ticksPerBeat, timeSig.num); + timeSigDenominatorPat->putValue(timeSig.beat * ticksPerBeat, timeSig.den); } + // manually call otherwise the pattern shows being 1 bar + timeSigNumeratorPat->updateLength(); + timeSigDenominatorPat->updateLength(); pd.setValue( 2 ); @@ -421,7 +431,7 @@ bool MidiImport::readSMF( TrackContainer* tc ) Note n( (ticks < 1 ? 1 : ticks ), noteEvt->get_start_time() * ticksPerBeat, noteEvt->get_identifier() - 12, - noteEvt->get_loud()); + noteEvt->get_loud() * (200.f / 127.f)); // Map from MIDI velocity to LMMS volume ch->addNote( n ); } diff --git a/plugins/MidiImport/portsmf/allegro.cpp b/plugins/MidiImport/portsmf/allegro.cpp index 653ff4c07..3f7b84073 100644 --- a/plugins/MidiImport/portsmf/allegro.cpp +++ b/plugins/MidiImport/portsmf/allegro.cpp @@ -54,8 +54,10 @@ void Alg_atoms::expand() maxlen += (maxlen >> 2); // add 25% char **new_atoms = new Alg_attribute[maxlen]; // now do copy - memcpy(new_atoms, atoms, len * sizeof(Alg_attribute)); - if (atoms) delete[] atoms; + if (atoms) { + memcpy(new_atoms, atoms, len * sizeof(Alg_attribute)); + delete[] atoms; + } atoms = new_atoms; } diff --git a/plugins/MultitapEcho/MultitapEcho.cpp b/plugins/MultitapEcho/MultitapEcho.cpp index be46a50c6..bff032dee 100644 --- a/plugins/MultitapEcho/MultitapEcho.cpp +++ b/plugins/MultitapEcho/MultitapEcho.cpp @@ -25,7 +25,7 @@ #include "MultitapEcho.h" #include "embed.h" - +#include "plugin_export.h" extern "C" { diff --git a/plugins/OpulenZ/OpulenZ.cpp b/plugins/OpulenZ/OpulenZ.cpp index 4b11102c3..4dde05b0f 100644 --- a/plugins/OpulenZ/OpulenZ.cpp +++ b/plugins/OpulenZ/OpulenZ.cpp @@ -59,6 +59,8 @@ #include "PixmapButton.h" #include "ToolTip.h" +#include "plugin_export.h" + extern "C" { @@ -77,9 +79,9 @@ Plugin::Descriptor PLUGIN_EXPORT opulenz_plugin_descriptor = }; // necessary for getting instance out of shared lib -PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *, void * _data ) +PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *m, void * ) { - return( new OpulenzInstrument( static_cast( _data ) ) ); + return( new OpulenzInstrument( static_cast( m ) ) ); } } @@ -679,7 +681,7 @@ void OpulenzInstrument::loadFile( const QString& file ) { OpulenzInstrumentView::OpulenzInstrumentView( Instrument * _instrument, QWidget * _parent ) : - InstrumentView( _instrument, _parent ) + InstrumentViewFixedSize( _instrument, _parent ) { #define KNOB_GEN(knobname, hinttext, hintunit,xpos,ypos) \ diff --git a/plugins/OpulenZ/OpulenZ.h b/plugins/OpulenZ/OpulenZ.h index e69c278ef..2273b355a 100644 --- a/plugins/OpulenZ/OpulenZ.h +++ b/plugins/OpulenZ/OpulenZ.h @@ -142,7 +142,7 @@ private: -class OpulenzInstrumentView : public InstrumentView +class OpulenzInstrumentView : public InstrumentViewFixedSize { Q_OBJECT public: diff --git a/plugins/ReverbSC/ReverbSC.cpp b/plugins/ReverbSC/ReverbSC.cpp index bfbd0390a..3d56fd0d0 100644 --- a/plugins/ReverbSC/ReverbSC.cpp +++ b/plugins/ReverbSC/ReverbSC.cpp @@ -1,7 +1,7 @@ /* * ReverbSC.cpp - A native reverb based on an algorithm by Sean Costello * - * This file is part of LMMS - http://lmms.io + * 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 @@ -24,6 +24,7 @@ #include "ReverbSC.h" #include "embed.h" +#include "plugin_export.h" #define DB2LIN(X) pow(10, X / 20.0f); diff --git a/plugins/ReverbSC/ReverbSC.h b/plugins/ReverbSC/ReverbSC.h index ba987414b..0e697c197 100644 --- a/plugins/ReverbSC/ReverbSC.h +++ b/plugins/ReverbSC/ReverbSC.h @@ -3,7 +3,7 @@ * * Copyright (c) 2017 Paul Batchelor * - * This file is part of LMMS - http://lmms.io + * 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 diff --git a/plugins/ReverbSC/ReverbSCControlDialog.cpp b/plugins/ReverbSC/ReverbSCControlDialog.cpp index 6b41415d9..9c9f3f44a 100644 --- a/plugins/ReverbSC/ReverbSCControlDialog.cpp +++ b/plugins/ReverbSC/ReverbSCControlDialog.cpp @@ -3,7 +3,7 @@ * * Copyright (c) 2017 Paul Batchelor * - * This file is part of LMMS - http://lmms.io + * 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 diff --git a/plugins/ReverbSC/ReverbSCControlDialog.h b/plugins/ReverbSC/ReverbSCControlDialog.h index 9f262a88f..0d9c1f51a 100644 --- a/plugins/ReverbSC/ReverbSCControlDialog.h +++ b/plugins/ReverbSC/ReverbSCControlDialog.h @@ -3,7 +3,7 @@ * * Copyright (c) 2017 Paul Batchelor * - * This file is part of LMMS - http://lmms.io + * 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 diff --git a/plugins/ReverbSC/ReverbSCControls.cpp b/plugins/ReverbSC/ReverbSCControls.cpp index ac6f8c689..0b9e337b4 100644 --- a/plugins/ReverbSC/ReverbSCControls.cpp +++ b/plugins/ReverbSC/ReverbSCControls.cpp @@ -3,7 +3,7 @@ * * Copyright (c) 2017 Paul Batchelor * - * This file is part of LMMS - http://lmms.io + * 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 diff --git a/plugins/ReverbSC/ReverbSCControls.h b/plugins/ReverbSC/ReverbSCControls.h index 638bdade9..36cc16a7e 100644 --- a/plugins/ReverbSC/ReverbSCControls.h +++ b/plugins/ReverbSC/ReverbSCControls.h @@ -3,7 +3,7 @@ * * Copyright (c) 2017 Paul Batchelor * - * This file is part of LMMS - http://lmms.io + * 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 diff --git a/plugins/ReverbSC/revsc.c b/plugins/ReverbSC/revsc.c index 35084c175..d9808963f 100644 --- a/plugins/ReverbSC/revsc.c +++ b/plugins/ReverbSC/revsc.c @@ -72,7 +72,7 @@ int sp_revsc_init(sp_data *sp, sp_revsc *p) sp_auxdata_alloc(&p->aux, nBytes); nBytes = 0; for (i = 0; i < 8; i++) { - p->delayLines[i].buf = (p->aux.ptr) + nBytes; + p->delayLines[i].buf = (SPFLOAT*) (((char*) p->aux.ptr) + nBytes); init_delay_line(p, &p->delayLines[i], i); nBytes += delay_line_bytes_alloc(sp->sr, 1, i); } diff --git a/plugins/SpectrumAnalyzer/Analyzer.cpp b/plugins/SpectrumAnalyzer/Analyzer.cpp new file mode 100644 index 000000000..9c3fe0814 --- /dev/null +++ b/plugins/SpectrumAnalyzer/Analyzer.cpp @@ -0,0 +1,75 @@ +/* + * Analyzer.cpp - definition of Analyzer class. + * + * Copyright (c) 2019 Martin Pavelek + * + * Based partially on Eq plugin code, + * Copyright (c) 2014-2017, David French + * + * 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. + * + */ + +#include "Analyzer.h" + +#include "embed.h" +#include "plugin_export.h" + + +extern "C" { + Plugin::Descriptor PLUGIN_EXPORT analyzer_plugin_descriptor = + { + "spectrumanalyzer", + "Spectrum Analyzer", + QT_TRANSLATE_NOOP("pluginBrowser", "A graphical spectrum analyzer."), + "Martin Pavelek ", + 0x0100, + Plugin::Effect, + new PluginPixmapLoader("logo"), + NULL, + NULL + }; +} + + +Analyzer::Analyzer(Model *parent, const Plugin::Descriptor::SubPluginFeatures::Key *key) : + Effect(&analyzer_plugin_descriptor, parent, key), + m_processor(&m_controls), + m_controls(this) +{ +} + + +// 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) +{ + if (!isEnabled() || !isRunning ()) {return false;} + if (m_controls.isViewVisible()) {m_processor.analyse(buffer, frame_count);} + return isRunning(); +} + + +extern "C" { + // needed for getting plugin out of shared lib + PLUGIN_EXPORT Plugin *lmms_plugin_main(Model *parent, void *data) + { + return new Analyzer(parent, static_cast(data)); + } +} + diff --git a/plugins/SpectrumAnalyzer/Analyzer.h b/plugins/SpectrumAnalyzer/Analyzer.h new file mode 100644 index 000000000..157cc1eae --- /dev/null +++ b/plugins/SpectrumAnalyzer/Analyzer.h @@ -0,0 +1,53 @@ +/* Analyzer.h - declaration of Analyzer class. + * + * Copyright (c) 2019 Martin Pavelek + * + * Based partially on Eq plugin code, + * Copyright (c) 2014-2017, David French + * + * 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 ANALYZER_H +#define ANALYZER_H + +#include "Effect.h" +#include "SaControls.h" +#include "SaProcessor.h" + + +//! Top level class; handles LMMS interface and feeds data to the data processor. +class Analyzer : public Effect +{ +public: + Analyzer(Model *parent, const Descriptor::SubPluginFeatures::Key *key); + virtual ~Analyzer() {}; + + bool processAudioBuffer(sampleFrame *buffer, const fpp_t frame_count) override; + EffectControls *controls() override {return &m_controls;} + + SaProcessor *getProcessor() {return &m_processor;} + +private: + SaProcessor m_processor; + SaControls m_controls; +}; + +#endif // ANALYZER_H + diff --git a/plugins/SpectrumAnalyzer/CMakeLists.txt b/plugins/SpectrumAnalyzer/CMakeLists.txt index c2aec0d43..630fbf1be 100644 --- a/plugins/SpectrumAnalyzer/CMakeLists.txt +++ b/plugins/SpectrumAnalyzer/CMakeLists.txt @@ -1,5 +1,5 @@ INCLUDE(BuildPlugin) INCLUDE_DIRECTORIES(${FFTW3F_INCLUDE_DIRS}) -LINK_DIRECTORIES(${FFTW3F_LIBRARY_DIRS}) LINK_LIBRARIES(${FFTW3F_LIBRARIES}) -BUILD_PLUGIN(spectrumanalyzer SpectrumAnalyzer.cpp SpectrumAnalyzerControls.cpp SpectrumAnalyzerControlDialog.cpp SpectrumAnalyzer.h SpectrumAnalyzerControls.h SpectrumAnalyzerControlDialog.h MOCFILES SpectrumAnalyzerControlDialog.h SpectrumAnalyzerControls.h EMBEDDED_RESOURCES *.png) +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) diff --git a/plugins/SpectrumAnalyzer/README.md b/plugins/SpectrumAnalyzer/README.md new file mode 100644 index 000000000..3d3506d65 --- /dev/null +++ b/plugins/SpectrumAnalyzer/README.md @@ -0,0 +1,19 @@ +# Spectrum Analyzer plugin + +## Overview + +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). + +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. + + +## Changelog + + 1.0.1 2019-06-02 + - code style changes + - added tool-tips + - use const for unmodified arrays passed to fft_helpers + 1.0.0 2019-04-07 + - initial release diff --git a/plugins/SpectrumAnalyzer/SaControls.cpp b/plugins/SpectrumAnalyzer/SaControls.cpp new file mode 100644 index 000000000..5691c0ae4 --- /dev/null +++ b/plugins/SpectrumAnalyzer/SaControls.cpp @@ -0,0 +1,144 @@ +/* + * SaControls.cpp - definition of SaControls class. + * + * 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. + * + */ + +#include "SaControls.h" + +#include + +#include "Analyzer.h" +#include "SaControlsDialog.h" + + +SaControls::SaControls(Analyzer *effect) : + EffectControls(effect), + m_effect(effect), + + // initialize bool models and set default values + m_pauseModel(false, this, tr("Pause")), + m_refFreezeModel(false, this, tr("Reference freeze")), + + m_waterfallModel(false, this, tr("Waterfall")), + m_smoothModel(false, this, tr("Averaging")), + m_stereoModel(false, this, tr("Stereo")), + m_peakHoldModel(false, this, tr("Peak hold")), + + m_logXModel(true, this, tr("Logarithmic frequency")), + m_logYModel(true, this, tr("Logarithmic amplitude")), + + // default values of combo boxes are set after they are populated + 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")) +{ + // Frequency and amplitude ranges; order must match + // FREQUENCY_RANGES and AMPLITUDE_RANGES defined in SaControls.h + m_freqRangeModel.addItem(tr("Full (auto)")); + m_freqRangeModel.addItem(tr("Audible")); + m_freqRangeModel.addItem(tr("Bass")); + m_freqRangeModel.addItem(tr("Mids")); + m_freqRangeModel.addItem(tr("High")); + 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"))); + + // FFT block size labels are generated automatically, based on + // FFT_BLOCK_SIZES vector defined in fft_helpers.h + for (unsigned int i = 0; i < FFT_BLOCK_SIZES.size(); i++) + { + if (i == 0) + { + m_blockSizeModel.addItem((std::to_string(FFT_BLOCK_SIZES[i]) + " ").c_str() + tr("(High time res.)")); + } + else if (i == FFT_BLOCK_SIZES.size() - 1) + { + m_blockSizeModel.addItem((std::to_string(FFT_BLOCK_SIZES[i]) + " ").c_str() + tr("(High freq. res.)")); + } + else + { + m_blockSizeModel.addItem(std::to_string(FFT_BLOCK_SIZES[i]).c_str()); + } + } + m_blockSizeModel.setValue(m_blockSizeModel.findText("2048")); + + // Window type order must match FFT_WINDOWS defined in fft_helpers.h + m_windowModel.addItem(tr("Rectangular (Off)")); + m_windowModel.addItem(tr("Blackman-Harris (Default)")); + m_windowModel.addItem(tr("Hamming")); + m_windowModel.addItem(tr("Hanning")); + m_windowModel.setValue(m_windowModel.findText(tr("Blackman-Harris (Default)"))); + + // 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). + m_colorL = QColor(51, 148, 204, 135); + m_colorR = QColor(204, 107, 51, 135); + m_colorMono = QColor(51, 148, 204, 204); + 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) +} + + +// Create the SaControlDialog widget which handles display of GUI elements. +EffectControlDialog* SaControls::createView() +{ + return new SaControlsDialog(this, m_effect->getProcessor()); +} + + +void SaControls::loadSettings(const QDomElement &_this) +{ + m_waterfallModel.loadSettings(_this, "Waterfall"); + m_smoothModel.loadSettings(_this, "Smooth"); + m_stereoModel.loadSettings(_this, "Stereo"); + m_peakHoldModel.loadSettings(_this, "PeakHold"); + m_logXModel.loadSettings(_this, "LogX"); + m_logYModel.loadSettings(_this, "LogY"); + m_freqRangeModel.loadSettings(_this, "RangeX"); + m_ampRangeModel.loadSettings(_this, "RangeY"); + m_blockSizeModel.loadSettings(_this, "BlockSize"); + m_windowModel.loadSettings(_this, "WindowType"); +} + + +void SaControls::saveSettings(QDomDocument &doc, QDomElement &parent) +{ + m_waterfallModel.saveSettings(doc, parent, "Waterfall"); + m_smoothModel.saveSettings(doc, parent, "Smooth"); + m_stereoModel.saveSettings(doc, parent, "Stereo"); + m_peakHoldModel.saveSettings(doc, parent, "PeakHold"); + m_logXModel.saveSettings(doc, parent, "LogX"); + m_logYModel.saveSettings(doc, parent, "LogY"); + m_freqRangeModel.saveSettings(doc, parent, "RangeX"); + m_ampRangeModel.saveSettings(doc, parent, "RangeY"); + m_blockSizeModel.saveSettings(doc, parent, "BlockSize"); + m_windowModel.saveSettings(doc, parent, "WindowType"); +} diff --git a/plugins/SpectrumAnalyzer/SaControls.h b/plugins/SpectrumAnalyzer/SaControls.h new file mode 100644 index 000000000..e0b54e6a2 --- /dev/null +++ b/plugins/SpectrumAnalyzer/SaControls.h @@ -0,0 +1,126 @@ +/* + * SaControls.h - declaration of SaControls class. + * + * 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 SACONTROLS_H +#define SACONTROLS_H + +#include "ComboBoxModel.h" +#include "EffectControls.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; + +// Holds all the configuration values +class SaControls : public EffectControls +{ + Q_OBJECT +public: + explicit SaControls(Analyzer* effect); + virtual ~SaControls() {} + + EffectControlDialog* createView() override; + + void saveSettings (QDomDocument& doc, QDomElement& parent) override; + void loadSettings (const QDomElement &_this) override; + + QString nodeName() const override {return "Analyzer";} + int controlCount() override {return 12;} + +private: + Analyzer *m_effect; + + BoolModel m_pauseModel; + BoolModel m_refFreezeModel; + + BoolModel m_waterfallModel; + BoolModel m_smoothModel; + BoolModel m_stereoModel; + BoolModel m_peakHoldModel; + + BoolModel m_logXModel; + BoolModel m_logYModel; + + ComboBoxModel m_freqRangeModel; + ComboBoxModel m_ampRangeModel; + ComboBoxModel m_blockSizeModel; + ComboBoxModel m_windowModel; + + QColor m_colorL; + QColor m_colorR; + QColor m_colorMono; + QColor m_colorBG; + QColor m_colorGrid; + QColor m_colorLabels; + + friend class SaControlsDialog; + friend class SaSpectrumView; + friend class SaWaterfallView; + friend class SaProcessor; +}; +#endif // SACONTROLS_H diff --git a/plugins/SpectrumAnalyzer/SaControlsDialog.cpp b/plugins/SpectrumAnalyzer/SaControlsDialog.cpp new file mode 100644 index 000000000..4ba307a4d --- /dev/null +++ b/plugins/SpectrumAnalyzer/SaControlsDialog.cpp @@ -0,0 +1,227 @@ +/* + * SaControlsDialog.cpp - definition of SaControlsDialog class. + * + * 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. + * + */ + +#include "SaControlsDialog.h" + +#include +#include +#include +#include +#include + +#include "ComboBox.h" +#include "ComboBoxModel.h" +#include "embed.h" +#include "Engine.h" +#include "LedCheckbox.h" +#include "PixmapButton.h" +#include "SaControls.h" +#include "SaProcessor.h" + + +// The entire GUI layout is built here. +SaControlsDialog::SaControlsDialog(SaControls *controls, SaProcessor *processor) : + EffectControlDialog(controls), + m_controls(controls), + m_processor(processor) +{ + // Top level placement of sections is handled by QSplitter widget. + QHBoxLayout *master_layout = new QHBoxLayout; + QSplitter *display_splitter = new QSplitter(Qt::Vertical); + master_layout->addWidget(display_splitter); + master_layout->setContentsMargins(2, 6, 2, 8); + setLayout(master_layout); + + // QSplitter top: configuration section + 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); + + // Pre-compute target pixmap size based on monitor DPI. + // Using setDevicePixelRatio() on pixmap allows the SVG image to be razor + // sharp on High-DPI screens, but the desired size must be manually + // 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; + + // pause and freeze buttons + PixmapButton *pauseButton = new PixmapButton(this, tr("Pause")); + pauseButton->setToolTip(tr("Pause data acquisition")); + QPixmap *pauseOnPixmap = new QPixmap(PLUGIN_NAME::getIconPixmap("play").scaled(buttonSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); + QPixmap *pauseOffPixmap = new QPixmap(PLUGIN_NAME::getIconPixmap("pause").scaled(buttonSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); + pauseOnPixmap->setDevicePixelRatio(devicePixelRatio()); + pauseOffPixmap->setDevicePixelRatio(devicePixelRatio()); + pauseButton->setActiveGraphic(*pauseOnPixmap); + pauseButton->setInactiveGraphic(*pauseOffPixmap); + pauseButton->setCheckable(true); + pauseButton->setModel(&controls->m_pauseModel); + config_layout->addWidget(pauseButton, 0, 0, 2, 1); + + PixmapButton *refFreezeButton = new PixmapButton(this, tr("Reference freeze")); + refFreezeButton->setToolTip(tr("Freeze current input as a reference / disable falloff in peak-hold mode.")); + QPixmap *freezeOnPixmap = new QPixmap(PLUGIN_NAME::getIconPixmap("freeze").scaled(buttonSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); + QPixmap *freezeOffPixmap = new QPixmap(PLUGIN_NAME::getIconPixmap("freeze_off").scaled(buttonSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); + freezeOnPixmap->setDevicePixelRatio(devicePixelRatio()); + freezeOffPixmap->setDevicePixelRatio(devicePixelRatio()); + refFreezeButton->setActiveGraphic(*freezeOnPixmap); + refFreezeButton->setInactiveGraphic(*freezeOffPixmap); + refFreezeButton->setCheckable(true); + refFreezeButton->setModel(&controls->m_refFreezeModel); + config_layout->addWidget(refFreezeButton, 2, 0, 2, 1); + + // misc configuration switches + LedCheckBox *waterfallButton = new LedCheckBox(tr("Waterfall"), this); + waterfallButton->setToolTip(tr("Display real-time spectrogram")); + waterfallButton->setCheckable(true); + waterfallButton->setMinimumSize(70, 12); + waterfallButton->setModel(&controls->m_waterfallModel); + config_layout->addWidget(waterfallButton, 0, 1); + + LedCheckBox *smoothButton = new LedCheckBox(tr("Averaging"), this); + smoothButton->setToolTip(tr("Enable exponential moving average")); + smoothButton->setCheckable(true); + smoothButton->setMinimumSize(70, 12); + smoothButton->setModel(&controls->m_smoothModel); + config_layout->addWidget(smoothButton, 1, 1); + + LedCheckBox *stereoButton = new LedCheckBox(tr("Stereo"), this); + stereoButton->setToolTip(tr("Display stereo channels separately")); + stereoButton->setCheckable(true); + stereoButton->setMinimumSize(70, 12); + stereoButton->setModel(&controls->m_stereoModel); + config_layout->addWidget(stereoButton, 2, 1); + + LedCheckBox *peakHoldButton = new LedCheckBox(tr("Peak hold"), this); + peakHoldButton->setToolTip(tr("Display envelope of peak values")); + peakHoldButton->setCheckable(true); + peakHoldButton->setMinimumSize(70, 12); + peakHoldButton->setModel(&controls->m_peakHoldModel); + config_layout->addWidget(peakHoldButton, 3, 1); + + // frequency: linear / log. switch and range selector + PixmapButton *logXButton = new PixmapButton(this, tr("Logarithmic frequency")); + logXButton->setToolTip(tr("Switch between logarithmic and linear frequency scale")); + QPixmap *logXOnPixmap = new QPixmap(PLUGIN_NAME::getIconPixmap("x_log").scaled(iconSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); + QPixmap *logXOffPixmap = new QPixmap(PLUGIN_NAME::getIconPixmap("x_linear").scaled(iconSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); + logXOnPixmap->setDevicePixelRatio(devicePixelRatio()); + logXOffPixmap->setDevicePixelRatio(devicePixelRatio()); + logXButton->setActiveGraphic(*logXOnPixmap); + logXButton->setInactiveGraphic(*logXOffPixmap); + logXButton->setCheckable(true); + logXButton->setModel(&controls->m_logXModel); + config_layout->addWidget(logXButton, 0, 2, 2, 1, Qt::AlignRight); + + ComboBox *freqRangeCombo = new ComboBox(this, tr("Frequency range")); + freqRangeCombo->setToolTip(tr("Frequency range")); + freqRangeCombo->setMinimumSize(100, 22); + freqRangeCombo->setMaximumSize(200, 22); + freqRangeCombo->setModel(&controls->m_freqRangeModel); + config_layout->addWidget(freqRangeCombo, 0, 3, 2, 1); + + // amplitude: linear / log switch and range selector + PixmapButton *logYButton = new PixmapButton(this, tr("Logarithmic amplitude")); + logYButton->setToolTip(tr("Switch between logarithmic and linear amplitude scale")); + QPixmap *logYOnPixmap = new QPixmap(PLUGIN_NAME::getIconPixmap("y_log").scaled(iconSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); + QPixmap *logYOffPixmap = new QPixmap(PLUGIN_NAME::getIconPixmap("y_linear").scaled(iconSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); + logYOnPixmap->setDevicePixelRatio(devicePixelRatio()); + logYOffPixmap->setDevicePixelRatio(devicePixelRatio()); + logYButton->setActiveGraphic(*logYOnPixmap); + logYButton->setInactiveGraphic(*logYOffPixmap); + logYButton->setCheckable(true); + logYButton->setModel(&controls->m_logYModel); + config_layout->addWidget(logYButton, 2, 2, 2, 1, Qt::AlignRight); + + ComboBox *ampRangeCombo = new ComboBox(this, tr("Amplitude range")); + ampRangeCombo->setToolTip(tr("Amplitude range")); + ampRangeCombo->setMinimumSize(100, 22); + ampRangeCombo->setMaximumSize(200, 22); + ampRangeCombo->setModel(&controls->m_ampRangeModel); + config_layout->addWidget(ampRangeCombo, 2, 3, 2, 1); + + // FFT: block size: icon and selector + QLabel *blockSizeLabel = new QLabel("", this); + QPixmap *blockSizeIcon = new QPixmap(PLUGIN_NAME::getIconPixmap("block_size")); + blockSizeIcon->setDevicePixelRatio(devicePixelRatio()); + blockSizeLabel->setPixmap(blockSizeIcon->scaled(iconSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); + config_layout->addWidget(blockSizeLabel, 0, 4, 2, 1, Qt::AlignRight); + + ComboBox *blockSizeCombo = new ComboBox(this, tr("FFT block bize")); + blockSizeCombo->setToolTip(tr("FFT block size")); + blockSizeCombo->setMinimumSize(100, 22); + blockSizeCombo->setMaximumSize(200, 22); + blockSizeCombo->setModel(&controls->m_blockSizeModel); + config_layout->addWidget(blockSizeCombo, 0, 5, 2, 1); + processor->reallocateBuffers(); + connect(&controls->m_blockSizeModel, &ComboBoxModel::dataChanged, [=] {processor->reallocateBuffers();}); + + // FFT: window type: icon and selector + QLabel *windowLabel = new QLabel("", this); + QPixmap *windowIcon = new QPixmap(PLUGIN_NAME::getIconPixmap("window")); + windowIcon->setDevicePixelRatio(devicePixelRatio()); + windowLabel->setPixmap(windowIcon->scaled(iconSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); + config_layout->addWidget(windowLabel, 2, 4, 2, 1, Qt::AlignRight); + + ComboBox *windowCombo = new ComboBox(this, tr("FFT window type")); + windowCombo->setToolTip(tr("FFT window type")); + windowCombo->setMinimumSize(100, 22); + windowCombo->setMaximumSize(200, 22); + windowCombo->setModel(&controls->m_windowModel); + config_layout->addWidget(windowCombo, 2, 5, 2, 1); + processor->rebuildWindow(); + connect(&controls->m_windowModel, &ComboBoxModel::dataChanged, [=] {processor->rebuildWindow();}); + + + // QSplitter middle and bottom: spectrum display widgets + m_spectrum = new SaSpectrumView(controls, processor, this); + display_splitter->addWidget(m_spectrum); + + m_waterfall = new SaWaterfallView(controls, processor, this); + display_splitter->addWidget(m_waterfall); + m_waterfall->setVisible(m_controls->m_waterfallModel.value()); + connect(&controls->m_waterfallModel, &BoolModel::dataChanged, [=] {m_waterfall->updateVisibility();}); +} + + +// Suggest the best current widget size. +QSize SaControlsDialog::sizeHint() const +{ + // Best width is determined by spectrum display sizeHint. + // Best height depends on whether waterfall is visible and + // consists of heights of the config section, spectrum, waterfall + // and some reserve for margins. + if (m_waterfall->isVisible()) + { + return QSize(m_spectrum->sizeHint().width(), + m_configHeight + m_spectrum->sizeHint().height() + m_waterfall->sizeHint().height() + 50); + } + else + { + return QSize(m_spectrum->sizeHint().width(), + m_configHeight + m_spectrum->sizeHint().height() + 50); + } +} + diff --git a/plugins/SpectrumAnalyzer/SaControlsDialog.h b/plugins/SpectrumAnalyzer/SaControlsDialog.h new file mode 100644 index 000000000..e5a35f186 --- /dev/null +++ b/plugins/SpectrumAnalyzer/SaControlsDialog.h @@ -0,0 +1,57 @@ +/* + * SaControlsDialog.h - declatation of SaControlsDialog class. + * + * 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 SACONTROLSDIALOG_H +#define SACONTROLSDIALOG_H + +#include "EffectControlDialog.h" +#include "SaControls.h" +#include "SaSpectrumView.h" +#include "SaProcessor.h" +#include "SaWaterfallView.h" + + +//! Top-level widget holding the configuration GUI and spectrum displays +class SaControlsDialog : public EffectControlDialog +{ + Q_OBJECT +public: + explicit SaControlsDialog(SaControls *controls, SaProcessor *processor); + virtual ~SaControlsDialog() {} + + bool isResizable() const override {return true;} + QSize sizeHint() const override; + +private: + SaControls *m_controls; + SaProcessor *m_processor; + + // Pointers to created widgets are needed to keep track of their sizeHint() changes. + // Config widget is a plain QWidget so it has just a fixed height instead. + const int m_configHeight = 75; + SaSpectrumView *m_spectrum; + SaWaterfallView *m_waterfall; +}; + +#endif // SACONTROLSDIALOG_H diff --git a/plugins/SpectrumAnalyzer/SaProcessor.cpp b/plugins/SpectrumAnalyzer/SaProcessor.cpp new file mode 100644 index 000000000..9261658aa --- /dev/null +++ b/plugins/SpectrumAnalyzer/SaProcessor.cpp @@ -0,0 +1,571 @@ +/* SaProcessor.cpp - implementation of SaProcessor class. + * + * Copyright (c) 2019 Martin Pavelek + * + * Based partially on Eq plugin code, + * Copyright (c) 2014-2017, David French + * + * 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. + * + */ + +#include "SaProcessor.h" + +#include +#include +#include +#include + +#include "lmms_math.h" + + +SaProcessor::SaProcessor(SaControls *controls) : + m_controls(controls), + m_inBlockSize(FFT_BLOCK_SIZES[0]), + m_fftBlockSize(FFT_BLOCK_SIZES[0]), + m_sampleRate(Engine::mixer()->processingSampleRate()), + m_framesFilledUp(0), + m_spectrumActive(false), + m_waterfallActive(false), + m_waterfallNotEmpty(0), + m_reallocating(false) +{ + 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_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_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(); +} + + +SaProcessor::~SaProcessor() +{ + if (m_fftPlanL != NULL) {fftwf_destroy_plan(m_fftPlanL);} + if (m_fftPlanR != NULL) {fftwf_destroy_plan(m_fftPlanR);} + if (m_spectrumL != NULL) {fftwf_free(m_spectrumL);} + if (m_spectrumR != NULL) {fftwf_free(m_spectrumR);} + + m_fftPlanL = NULL; + m_fftPlanR = NULL; + m_spectrumL = NULL; + m_spectrumR = NULL; +} + + +// 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) +{ + #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()) + { + const bool stereo = m_controls->m_stereoModel.value(); + fpp_t in_frame = 0; + while (in_frame < frame_count) + { + // 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. + // 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++) + { + // 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()) + { + // Logarithmic scale + if (band_end - band_start > 1.0) + { + // band spans multiple pixels: draw all pixels it covers + for (target = (int)band_start; target < (int)band_end; target++) + { + if (target >= 0 && target < binCount()) + { + 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 + { + // 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]); + } + } + } + } + } + #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 + m_framesFilledUp = 0; + } + } +} + + +// Produce a spectrogram pixel from normalized spectrum data. +// Values over 1.0 will cause the color components to overflow: this is left +// intentionally untreated as it clearly indicates which frequency is clipping. +// 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 +{ + if (m_controls->m_stereoModel.value()) + { + float ampL = pow(left, gamma_correction); + float ampR = pow(right, gamma_correction); + return qRgb(m_controls->m_colorL.red() * ampL + m_controls->m_colorR.red() * ampR, + m_controls->m_colorL.green() * ampL + m_controls->m_colorR.green() * ampR, + m_controls->m_colorL.blue() * ampL + m_controls->m_colorR.blue() * ampR); + } + else + { + 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); + } +} + + + +// Inform the processor whether any display widgets actually need it. +void SaProcessor::setSpectrumActive(bool active) +{ + m_spectrumActive = active; +} + +void SaProcessor::setWaterfallActive(bool active) +{ + m_waterfallActive = active; +} + + +// Reallocate data buffers according to newly set block size. +void SaProcessor::reallocateBuffers() +{ + unsigned int new_size_index = m_controls->m_blockSizeModel.value(); + unsigned int new_in_size, new_fft_size; + unsigned int new_bins; + + // get new block sizes and bin count based on selected index + if (new_size_index < FFT_BLOCK_SIZES.size()) + { + new_in_size = FFT_BLOCK_SIZES[new_size_index]; + } + else + { + new_in_size = FFT_BLOCK_SIZES.back(); + } + if (new_size_index + m_zeroPadFactor < FFT_BLOCK_SIZES.size()) + { + new_fft_size = FFT_BLOCK_SIZES[new_size_index + m_zeroPadFactor]; + } + else + { + new_fft_size = FFT_BLOCK_SIZES.back(); + } + + 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. + m_reallocating = true; + QMutexLocker lock(&m_dataAccess); + + // destroy old FFT plan and free the result buffer + if (m_fftPlanL != NULL) {fftwf_destroy_plan(m_fftPlanL);} + if (m_fftPlanR != NULL) {fftwf_destroy_plan(m_fftPlanR);} + if (m_spectrumL != NULL) {fftwf_free(m_spectrumL);} + if (m_spectrumR != NULL) {fftwf_free(m_spectrumR);} + + // 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_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); + + if (m_fftPlanL == NULL || m_fftPlanR == NULL) + { + std::cerr << "Failed to create new FFT plan!" << std::endl; + } + 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); + + // done; publish new sizes and clean up + m_inBlockSize = new_in_size; + m_fftBlockSize = new_fft_size; + + lock.unlock(); + m_reallocating = false; + clear(); +} + + +// Precompute a new FFT window based on currently selected type. +void SaProcessor::rebuildWindow() +{ + // computation is done in fft_helpers + QMutexLocker lock(&m_dataAccess); + precomputeWindow(m_fftWindow.data(), m_inBlockSize, (FFT_WINDOWS) m_controls->m_windowModel.value()); +} + + +// Clear all data buffers and replace contents with zeros. +// Note: may take a few milliseconds, do not call in a loop! +void SaProcessor::clear() +{ + QMutexLocker lock(&m_dataAccess); + m_framesFilledUp = 0; + std::fill(m_bufferL.begin(), m_bufferL.end(), 0); + std::fill(m_bufferR.begin(), m_bufferR.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.begin(), m_history.end(), 0); +} + + +// -------------------------------------- +// Frequency conversion helpers +// + +// Get sample rate value that is valid for currently stored results. +unsigned int SaProcessor::getSampleRate() const +{ + return m_sampleRate; +} + + +// Maximum frequency of a sampled signal is equal to half of its sample rate. +float SaProcessor::getNyquistFreq() const +{ + return getSampleRate() / 2.0f; +} + + +// FFTW automatically discards upper half of the symmetric FFT output, so +// the useful bin count is the transform size divided by 2, plus zero. +unsigned int SaProcessor::binCount() const +{ + return m_fftBlockSize / 2 + 1; +} + + +// Return the center frequency of given frequency bin. +float SaProcessor::binToFreq(unsigned int bin_index) const +{ + return getNyquistFreq() * bin_index / binCount(); +} + + +// Return width of the frequency range that falls into one bin. +// The binCount is lowered by one since half of the first and last bin is +// actually outside the frequency range. +float SaProcessor::binBandwidth() const +{ + return getNyquistFreq() / (binCount() - 1); +} + + +float SaProcessor::getFreqRangeMin(bool linear) const +{ + switch (m_controls->m_freqRangeModel.value()) + { + case FRANGE_AUDIBLE: return FRANGE_AUDIBLE_START; + case FRANGE_BASS: return FRANGE_BASS_START; + case FRANGE_MIDS: return FRANGE_MIDS_START; + case FRANGE_HIGH: return FRANGE_HIGH_START; + default: + case FRANGE_FULL: return linear ? 0 : LOWEST_LOG_FREQ; + } +} + + +float SaProcessor::getFreqRangeMax() const +{ + switch (m_controls->m_freqRangeModel.value()) + { + case FRANGE_AUDIBLE: return FRANGE_AUDIBLE_END; + case FRANGE_BASS: return FRANGE_BASS_END; + case FRANGE_MIDS: return FRANGE_MIDS_END; + case FRANGE_HIGH: return FRANGE_HIGH_END; + default: + case FRANGE_FULL: return getNyquistFreq(); + } +} + + +// Map frequency to pixel x position on a display of given width. +float SaProcessor::freqToXPixel(float freq, unsigned int width) const +{ + if (m_controls->m_logXModel.value()) + { + if (freq <= 1) {return 0;} + float min = log10(getFreqRangeMin()); + float range = log10(getFreqRangeMax()) - min; + return (log10(freq) - min) / range * width; + } + else + { + float min = getFreqRangeMin(); + float range = getFreqRangeMax() - min; + return (freq - min) / range * width; + } +} + + +// Map pixel x position on display of given width back to frequency. +float SaProcessor::xPixelToFreq(float x, unsigned int width) const +{ + if (m_controls->m_logXModel.value()) + { + float min = log10(getFreqRangeMin()); + float max = log10(getFreqRangeMax()); + float range = max - min; + return pow(10, min + x / width * range); + } + else + { + float min = getFreqRangeMin(); + float range = getFreqRangeMax() - min; + return min + x / width * range; + } +} + + +// -------------------------------------- +// Amplitude conversion helpers +// +float SaProcessor::getAmpRangeMin(bool linear) const +{ + // return very low limit to make sure zero gets included at linear grid + if (linear) {return -900;} + 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; + default: + case ARANGE_DEFAULT: return ARANGE_DEFAULT_START; + } +} + + +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; + default: + case ARANGE_DEFAULT: return ARANGE_DEFAULT_END; + } +} + + +// Map linear amplitude to pixel y position on a display of given height. +// Note that display coordinates are flipped: amplitude grows from [height] to zero. +float SaProcessor::ampToYPixel(float amplitude, unsigned int height) const +{ + if (m_controls->m_logYModel.value()) + { + // logarithmic scale: convert linear amplitude to dB (relative to 1.0) + float amplitude_dB = 10 * log10(amplitude); + if (amplitude_dB < getAmpRangeMin()) + { + return height; + } + else + { + float max = getAmpRangeMax(); + float range = getAmpRangeMin() - max; + return (amplitude_dB - max) / range * height; + } + } + else + { + // linear scale: convert returned ranges from dB to linear scale + float max = pow(10, getAmpRangeMax() / 10); + float range = pow(10, getAmpRangeMin() / 10) - max; + return (amplitude - max) / range * height; + } +} + + +// Map pixel y position on display of given height back to amplitude. +// Note that display coordinates are flipped: amplitude grows from [height] to zero. +// Also note that in logarithmic Y mode the returned amplitude is in dB, not linear. +float SaProcessor::yPixelToAmp(float y, unsigned int height) const +{ + if (m_controls->m_logYModel.value()) + { + float max = getAmpRangeMax(); + float range = getAmpRangeMin() - max; + return max + range * (y / height); + } + else + { + // linear scale: convert returned ranges from dB to linear scale + float max = pow(10, getAmpRangeMax() / 10); + float range = pow(10, getAmpRangeMin() / 10) - max; + return max + range * (y / height); + } +} + diff --git a/plugins/SpectrumAnalyzer/SaProcessor.h b/plugins/SpectrumAnalyzer/SaProcessor.h new file mode 100644 index 000000000..ae2df16f8 --- /dev/null +++ b/plugins/SpectrumAnalyzer/SaProcessor.h @@ -0,0 +1,122 @@ +/* SaProcessor.h - declaration of SaProcessor class. + * + * Copyright (c) 2019 Martin Pavelek + * + * Based partially on Eq plugin code, + * Copyright (c) 2014 David French + * + * 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 SAPROCESSOR_H +#define SAPROCESSOR_H + +#include +#include +#include + +#include "fft_helpers.h" +#include "SaControls.h" + + +//! Receives audio data, runs FFT analysis and stores the result. +class SaProcessor +{ +public: + explicit SaProcessor(SaControls *controls); + virtual ~SaProcessor(); + + void analyse(sampleFrame *in_buffer, const fpp_t frame_count); + + // inform processor if any processing is actually required + void setSpectrumActive(bool active); + void setWaterfallActive(bool active); + + // configuration is taken from models in SaControls; some changes require + // an exlicit update request (reallocation and window rebuild) + void reallocateBuffers(); + void rebuildWindow(); + void clear(); + + // information about results and unit conversion helpers + float binToFreq(unsigned int bin_index) const; + float binBandwidth() const; + + float freqToXPixel(float frequency, unsigned int width) const; + float xPixelToFreq(float x, unsigned int width) const; + + float ampToYPixel(float amplitude, unsigned int height) const; + float yPixelToAmp(float y, unsigned int height) const; + + unsigned int getSampleRate() const; + float getNyquistFreq() const; + + float getFreqRangeMin(bool linear = false) const; + float getFreqRangeMax() const; + 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 + QMutex m_dataAccess; + +private: + SaControls *m_controls; + + // 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_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 + fftwf_plan m_fftPlanL; + fftwf_plan m_fftPlanR; + fftwf_complex *m_spectrumL; //!< frequency domain samples (complex) (left) + fftwf_complex *m_spectrumR; //!< frequency domain samples (complex) (right) + std::vector m_absSpectrumL; //!< frequency domain samples (absolute) (left) + std::vector m_absSpectrumR; //!< frequency domain samples (absolute) (right) + std::vector m_normSpectrumL; //!< frequency domain samples (normalized) (left) + 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. + + // book keeping + bool m_spectrumActive; + bool m_waterfallActive; + unsigned int m_waterfallNotEmpty; + 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; + + friend class SaSpectrumView; + friend class SaWaterfallView; +}; +#endif // SAPROCESSOR_H + diff --git a/plugins/SpectrumAnalyzer/SaSpectrumView.cpp b/plugins/SpectrumAnalyzer/SaSpectrumView.cpp new file mode 100644 index 000000000..746d52cfd --- /dev/null +++ b/plugins/SpectrumAnalyzer/SaSpectrumView.cpp @@ -0,0 +1,796 @@ +/* SaSpectrumView.cpp - implementation of SaSpectrumView class. + * + * Copyright (c) 2019 Martin Pavelek + * + * Based partially on Eq plugin code, + * Copyright (c) 2014-2017, David French + * + * 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. + * + */ + +#include "SaSpectrumView.h" + +#include +#include +#include +#include +#include +#include + +#include "GuiApplication.h" +#include "MainWindow.h" +#include "SaProcessor.h" + +#ifdef SA_DEBUG + #include + #include +#endif + + +SaSpectrumView::SaSpectrumView(SaControls *controls, SaProcessor *processor, QWidget *_parent) : + QWidget(_parent), + m_controls(controls), + m_processor(processor), + m_freezeRequest(false), + m_frozen(false) +{ + setMinimumSize(360, 170); + setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); + + connect(gui->mainWindow(), SIGNAL(periodicUpdate()), this, SLOT(periodicUpdate())); + + m_displayBufferL.resize(m_processor->binCount(), 0); + m_displayBufferR.resize(m_processor->binCount(), 0); + m_peakBufferL.resize(m_processor->binCount(), 0); + m_peakBufferR.resize(m_processor->binCount(), 0); + + m_freqRangeIndex = m_controls->m_freqRangeModel.value(); + m_ampRangeIndex = m_controls->m_ampRangeModel.value(); + + m_logFreqTics = makeLogFreqTics(m_processor->getFreqRangeMin(), m_processor->getFreqRangeMax()); + m_linearFreqTics = makeLinearFreqTics(m_processor->getFreqRangeMin(), m_processor->getFreqRangeMax()); + m_logAmpTics = makeLogAmpTics(m_processor->getAmpRangeMin(), m_processor->getAmpRangeMax()); + m_linearAmpTics = makeLinearAmpTics(m_processor->getAmpRangeMin(), m_processor->getAmpRangeMax()); + + m_cursor = QPoint(0, 0); +} + + +// Compose and draw all the content; periodically called by Qt. +// NOTE: Performance sensitive! If the drawing takes too long, it will drag +// the FPS down for the entire program! Use SA_DEBUG to display timings. +void SaSpectrumView::paintEvent(QPaintEvent *event) +{ + #ifdef SA_DEBUG + int total_time = std::chrono::high_resolution_clock::now().time_since_epoch().count(); + #endif + + // 0) Constants and init + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing, true); + + // drawing and path-making are split into multiple methods for clarity; + // display boundaries are updated here and shared as member variables + m_displayTop = 1; + m_displayBottom = height() -20; + m_displayLeft = 26; + m_displayRight = width() -26; + m_displayWidth = m_displayRight - m_displayLeft; + + // recompute range labels if needed + if (m_freqRangeIndex != m_controls->m_freqRangeModel.value()) + { + m_logFreqTics = makeLogFreqTics(m_processor->getFreqRangeMin(), m_processor->getFreqRangeMax()); + m_linearFreqTics = makeLinearFreqTics(m_processor->getFreqRangeMin(true), m_processor->getFreqRangeMax()); + m_freqRangeIndex = m_controls->m_freqRangeModel.value(); + } + if (m_ampRangeIndex != m_controls->m_ampRangeModel.value()) + { + m_logAmpTics = makeLogAmpTics(m_processor->getAmpRangeMin(), m_processor->getAmpRangeMax()); + m_linearAmpTics = makeLinearAmpTics(m_processor->getAmpRangeMin(true), m_processor->getAmpRangeMax()); + m_ampRangeIndex = m_controls->m_ampRangeModel.value(); + } + + // generate freeze request or clear "frozen" status based on freeze button + if (!m_frozen && m_controls->m_refFreezeModel.value()) + { + m_freezeRequest = true; + } + else if (!m_controls->m_refFreezeModel.value()) + { + m_frozen = false; + } + + // 1) Background, grid and labels + drawGrid(painter); + + // 2) Spectrum display + drawSpectrum(painter); + + // 3) Overlays + // draw cursor (if it is within bounds) + drawCursor(painter); + + // always draw the display outline + painter.setPen(QPen(m_controls->m_colorGrid, 2, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + painter.drawRoundedRect(m_displayLeft, 1, + m_displayWidth, m_displayBottom, + 2.0, 2.0); + + #ifdef SA_DEBUG + // display what FPS would be achieved if spectrum display ran in a loop + total_time = std::chrono::high_resolution_clock::now().time_since_epoch().count() - total_time; + 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())); + #endif +} + + +// Refresh data and draw the spectrum. +void SaSpectrumView::drawSpectrum(QPainter &painter) +{ + #ifdef SA_DEBUG + int path_time = 0, 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)) + { + 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 + draw_time = std::chrono::high_resolution_clock::now().time_since_epoch().count(); + #endif + // in case stereo is disabled, mono data are stored in left channel structures + if (m_controls->m_stereoModel.value()) + { + painter.fillPath(m_pathR, QBrush(m_controls->m_colorR)); + painter.fillPath(m_pathL, QBrush(m_controls->m_colorL)); + } + else + { + painter.fillPath(m_pathL, QBrush(m_controls->m_colorMono)); + } + // draw the peakBuffer only if peak hold or reference freeze is active + if (m_controls->m_peakHoldModel.value() || m_controls->m_refFreezeModel.value()) + { + if (m_controls->m_stereoModel.value()) + { + painter.setPen(QPen(m_controls->m_colorR, 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + painter.drawPath(m_pathPeakR); + painter.setPen(QPen(m_controls->m_colorL, 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + painter.drawPath(m_pathPeakL); + } + else + { + painter.setPen(QPen(m_controls->m_colorL, 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + painter.drawPath(m_pathPeakL); + } + } + #ifdef SA_DEBUG + 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())); + #endif +} + + +// Read newest FFT results from SaProcessor, update local display buffers +// 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); + + // check if bin count changed and reallocate display buffers accordingly + if (m_processor->binCount() != m_displayBufferL.size()) + { + m_displayBufferL.clear(); + m_displayBufferR.clear(); + m_peakBufferL.clear(); + m_peakBufferR.clear(); + m_displayBufferL.resize(m_processor->binCount(), 0); + m_displayBufferR.resize(m_processor->binCount(), 0); + m_peakBufferL.resize(m_processor->binCount(), 0); + m_peakBufferR.resize(m_processor->binCount(), 0); + } + + // update display buffers for left and right channel + #ifdef SA_DEBUG + 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()); + #ifdef SA_DEBUG + refresh_time = std::chrono::high_resolution_clock::now().time_since_epoch().count() - refresh_time; + #endif + + // if there was a freeze request, it was taken care of during the update + if (m_controls->m_refFreezeModel.value() && m_freezeRequest) + { + m_freezeRequest = false; + m_frozen = true; + } + + #ifdef SA_DEBUG + int make_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); + if (m_controls->m_stereoModel.value()) + { + m_pathR = makePath(m_displayBufferR, 1.5); + } + if (m_controls->m_peakHoldModel.value() || m_controls->m_refFreezeModel.value()) + { + m_pathPeakL = makePath(m_peakBufferL, 0.25); + if (m_controls->m_stereoModel.value()) + { + m_pathPeakR = makePath(m_peakBufferR, 0.25); + } + } + #ifdef SA_DEBUG + make_time = std::chrono::high_resolution_clock::now().time_since_epoch().count() - make_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; + #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) +{ + for (int n = 0; n < m_processor->binCount(); n++) + { + // Update the exponential average if enabled, or simply copy the value. + if (!m_controls->m_pauseModel.value()) + { + if (m_controls->m_smoothModel.value()) + { + displayBuffer[n] = spectrum[n] * m_smoothFactor + displayBuffer[n] * (1 - m_smoothFactor); + } + else + { + displayBuffer[n] = spectrum[n]; + } + } + // Update peak-hold and reference freeze data (using a shared curve). + // Peak hold and freeze can be combined: decay only if not frozen. + // Ref. freeze operates on the (possibly averaged) display buffer. + if (m_controls->m_refFreezeModel.value() && m_freezeRequest) + { + peakBuffer[n] = displayBuffer[n]; + } + else if (m_controls->m_peakHoldModel.value() && !m_controls->m_pauseModel.value()) + { + if (spectrum[n] > peakBuffer[n]) + { + peakBuffer[n] = spectrum[n]; + } + else if (!m_controls->m_refFreezeModel.value()) + { + peakBuffer[n] = peakBuffer[n] * m_peakDecayFactor; + } + } + else if (!m_controls->m_refFreezeModel.value() && !m_controls->m_peakHoldModel.value()) + { + peakBuffer[n] = 0; + } + // take note if there was actually anything to display + m_decaySum += displayBuffer[n] + peakBuffer[n]; + } +} + + +// Use display buffer to build a path that can be drawn or filled by QPainter. +// Resolution controls the performance / quality tradeoff; the value specifies +// number of points in x axis per device pixel. Values over 1.0 still +// contribute to quality and accuracy thanks to anti-aliasing. +QPainterPath SaSpectrumView::makePath(std::vector &displayBuffer, float resolution = 1.0) +{ + // convert resolution to number of path points per logical pixel + float pixel_limit = resolution * window()->devicePixelRatio(); + + QPainterPath path; + path.moveTo(m_displayLeft, m_displayBottom); + + // Translate frequency bins to path points. + // Display is flipped: y values grow towards zero, initial max is bottom. + // Bins falling to interval [x_start, x_next) contribute to a single point. + float max = m_displayBottom; + float x_start = -1; // lower bound of currently constructed point + for (unsigned int n = 0; n < m_processor->binCount(); n++) + { + float x = freqToXPixel(binToFreq(n), m_displayWidth); + float x_next = freqToXPixel(binToFreq(n + 1), m_displayWidth); + float y = ampToYPixel(displayBuffer[n], m_displayBottom); + + // consider making a point only if x falls within display bounds + if (0 < x && x < m_displayWidth) + { + if (x_start == -1) + { + x_start = x; + // the first displayed bin is stretched to the left edge to prevent + // creating a misleading slope leading to zero (at log. scale) + path.lineTo(m_displayLeft, y + m_displayTop); + } + // Opt.: QPainter is very slow -- draw at most [pixel_limit] points + // per logical pixel. As opposed to limiting the bin count, this + // allows high resolution display if user resizes the analyzer. + // Look at bins that share the pixel and use the highest value: + max = y < max ? y : max; + // And make the final point in the middle of current interval. + if ((int)(x * pixel_limit) != (int)(x_next * pixel_limit)) + { + x = (x + x_start) / 2; + path.lineTo(x + m_displayLeft, max + m_displayTop); + max = m_displayBottom; + x_start = x_next; + } + } + else + { + // stop processing after a bin falls outside right edge + // and align it to the edge to prevent a gap + if (n > 0 && x > 0) + { + path.lineTo(m_displayRight, y + m_displayTop); + break; + } + } + } + path.lineTo(m_displayRight, m_displayBottom); + path.closeSubpath(); + return path; +} + + +// Draw background, grid and associated frequency and amplitude labels. +void SaSpectrumView::drawGrid(QPainter &painter) +{ + std::vector> *freqTics = NULL; + std::vector> *ampTics = NULL; + float pos = 0; + float label_width = 24; + float label_height = 15; + float margin = 5; + + // always draw the background + painter.fillRect(m_displayLeft, m_displayTop, + m_displayWidth, m_displayBottom, + m_controls->m_colorBG); + + // select logarithmic or linear frequency grid and draw it + if (m_controls->m_logXModel.value()) + { + freqTics = &m_logFreqTics; + } + else + { + freqTics = &m_linearFreqTics; + } + // draw frequency grid (line.first is display position) + painter.setPen(QPen(m_controls->m_colorGrid, 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + for (auto &line: *freqTics) + { + painter.drawLine(m_displayLeft + freqToXPixel(line.first, m_displayWidth), + 2, + m_displayLeft + freqToXPixel(line.first, m_displayWidth), + m_displayBottom); + } + // print frequency labels (line.second is label) + painter.setPen(QPen(m_controls->m_colorLabels, 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + for (auto & line: *freqTics) + { + pos = m_displayLeft + freqToXPixel(line.first, m_displayWidth); + // align first and last label to the edge if needed, otherwise center them + if (line == freqTics->front() && pos - label_width / 2 < m_displayLeft) + { + painter.drawText(m_displayLeft, m_displayBottom + margin, + label_width, label_height, Qt::AlignLeft | Qt::TextDontClip, + QString(line.second.c_str())); + } + else if (line == freqTics->back() && pos + label_width / 2 > m_displayRight) + { + painter.drawText(m_displayRight - label_width, m_displayBottom + margin, + label_width, label_height, Qt::AlignRight | Qt::TextDontClip, + QString(line.second.c_str())); + } + else + { + painter.drawText(pos - label_width / 2, m_displayBottom + margin, + label_width, label_height, Qt::AlignHCenter | Qt::TextDontClip, + QString(line.second.c_str())); + } + } + + margin = 2; + // select logarithmic or linear amplitude grid and draw it + if (m_controls->m_logYModel.value()) + { + ampTics = &m_logAmpTics; + } + else + { + ampTics = &m_linearAmpTics; + } + // draw amplitude grid + painter.setPen(QPen(m_controls->m_colorGrid, 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + for (auto & line: *ampTics) + { + painter.drawLine(m_displayLeft + 1, + ampToYPixel(line.first, m_displayBottom), + m_displayRight - 1, + ampToYPixel(line.first, m_displayBottom)); + } + // print amplitude labels + painter.setPen(QPen(m_controls->m_colorLabels, 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + bool stereo = m_controls->m_stereoModel.value(); + for (auto & line: *ampTics) + { + pos = ampToYPixel(line.first, m_displayBottom); + // align first and last labels to edge if needed, otherwise center them + if (line == ampTics->back() && pos < 8) + { + if (stereo) + { + painter.setPen(QPen(m_controls->m_colorL.lighter(), 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + } + painter.drawText(m_displayLeft - label_width - margin, m_displayTop - 2, + label_width, label_height, Qt::AlignRight | Qt::AlignTop | Qt::TextDontClip, + QString(line.second.c_str())); + if (stereo) + { + painter.setPen(QPen(m_controls->m_colorR.lighter(), 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + } + painter.drawText(m_displayRight + margin, m_displayTop - 2, + label_width, label_height, Qt::AlignLeft | Qt::AlignTop | Qt::TextDontClip, + QString(line.second.c_str())); + } + else if (line == ampTics->front() && pos > m_displayBottom - label_height) + { + if (stereo) + { + painter.setPen(QPen(m_controls->m_colorL.lighter(), 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + } + painter.drawText(m_displayLeft - label_width - margin, m_displayBottom - label_height + 2, + label_width, label_height, Qt::AlignRight | Qt::AlignBottom | Qt::TextDontClip, + QString(line.second.c_str())); + if (stereo) + { + painter.setPen(QPen(m_controls->m_colorR.lighter(), 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + } + 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 + { + if (stereo) + { + painter.setPen(QPen(m_controls->m_colorL.lighter(), 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + } + 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())); + if (stereo) + { + painter.setPen(QPen(m_controls->m_colorR.lighter(), 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + } + 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 cursor and its coordinates if it is within display bounds. +void SaSpectrumView::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(m_cursor.x(), m_displayTop, m_cursor.x(), m_displayBottom); + painter.drawLine(m_displayLeft, m_cursor.y(), m_displayRight, m_cursor.y()); + + // coordinates + 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"); + + 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); + + // 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()); + } + 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()); + } + painter.drawText(m_displayRight -60, 30, 100, 16, Qt::AlignLeft, tmps); + } +} + + +// Wrappers for most used SaProcessor helpers (to make local code more compact). +float SaSpectrumView::binToFreq(unsigned int bin_index) +{ + return m_processor->binToFreq(bin_index); +} + + +float SaSpectrumView::freqToXPixel(float frequency, unsigned int width) +{ + return m_processor->freqToXPixel(frequency, width); +} + + +float SaSpectrumView::ampToYPixel(float amplitude, unsigned int height) +{ + return m_processor->ampToYPixel(amplitude, height); +} + + +// Generate labels suitable for logarithmic frequency scale. +// Low / high limits are in Hz. Lowest possible label is 10 Hz. +std::vector> SaSpectrumView::makeLogFreqTics(int low, int high) +{ + std::vector> result; + int i, j; + int a[] = {10, 20, 50}; // sparse series multipliers + int b[] = {14, 30, 70}; // additional (denser) series + + // generate main steps (powers of 10); use the series to specify smaller steps + for (i = 1; i <= high; i *= 10) + { + for (j = 0; j < 3; j++) + { + // insert a label from sparse series if it falls within bounds + if (i * a[j] >= low && i * a[j] <= high) + { + if (i * a[j] < 1000) + { + result.emplace_back(i * a[j], std::to_string(i * a[j])); + } + else + { + result.emplace_back(i * a[j], std::to_string(i * a[j] / 1000) + "k"); + } + } + // also insert denser series if high and low values are close + if ((log10(high) - log10(low) < 2) && (i * b[j] >= low && i * b[j] <= high)) + { + if (i * b[j] < 1500) + { + result.emplace_back(i * b[j], std::to_string(i * b[j])); + } + else + { + result.emplace_back(i * b[j], std::to_string(i * b[j] / 1000) + "k"); + } + } + } + } + return result; +} + + +// Generate labels suitable for linear frequency scale. +// Low / high limits are in Hz. +std::vector> SaSpectrumView::makeLinearFreqTics(int low, int high) +{ + std::vector> result; + int i, increment; + + // select a suitable increment based on zoom level + if (high - low < 500) {increment = 50;} + else if (high - low < 1000) {increment = 100;} + else if (high - low < 5000) {increment = 1000;} + else {increment = 2000;} + + // generate steps based on increment, starting at 0 + for (i = 0; i <= high; i += increment) + { + if (i >= low) + { + if (i < 1000) + { + result.emplace_back(i, std::to_string(i)); + } + else + { + result.emplace_back(i, std::to_string(i/1000) + "k"); + } + } + } + return result; +} + + +// Generate labels suitable for logarithmic (dB) amplitude scale. +// Low / high limits are in dB; 0 dB amplitude = 1.0 linear. +// Treating results as power ratio, i.e., 3 dB should be about twice as loud. +std::vector> SaSpectrumView::makeLogAmpTics(int low, int high) +{ + std::vector> result; + float i; + double increment; + + // Base zoom level on selected range and how close is the current height + // to the sizeHint() (denser scale for bigger window). + if ((high - low) < 20 * ((float)height() / sizeHint().height())) + { + increment = pow(10, 0.3); // 3 dB steps when really zoomed in + } + else if (high - low < 45 * ((float)height() / sizeHint().height())) + { + increment = pow(10, 0.6); // 6 dB steps when sufficiently zoomed in + } + else + { + increment = 10; // 10 dB steps otherwise + } + + // Generate n dB increments, start checking at -90 dB. Limits are tweaked + // just a little bit to make sure float comparisons do not miss edges. + for (i = 0.000000001; 10 * log10(i) <= (high + 0.001); i *= increment) + { + if (10 * log10(i) >= (low - 0.001)) + { + result.emplace_back(i, std::to_string((int)std::round(10 * log10(i)))); + } + } + return result; +} + + +// Generate labels suitable for linear amplitude scale. +// Low / high limits are in dB; 0 dB amplitude = 1.0 linear. +// Smallest possible label is 0.001, largest is 999. This includes the majority +// of useful labels; going lower or higher would require increasing margin size +// so that the text can fit. That would be a waste of space -- the linear scale +// would only make the experience worse for the main, logarithmic (dB) scale. +std::vector> SaSpectrumView::makeLinearAmpTics(int low, int high) +{ + std::vector> result; + double i, nearest; + + // make about 5 labels when window is small, 10 if it is big + float split = (float)height() / sizeHint().height() >= 1.5 ? 10.0 : 5.0; + + // convert limits to linear scale + float lin_low = pow(10, low / 10.0); + float lin_high = pow(10, high / 10.0); + + // Linear scale will vary widely, so instead of trying to craft extra nice + // multiples, just generate a few evenly spaced increments across the range, + // paying attention only to the decimal places to keep labels short. + // Limits are shifted a bit so that float comparisons do not miss edges. + for (i = 0; i <= (lin_high + 0.0001); i += (lin_high - lin_low) / split) + { + if (i >= (lin_low - 0.0001)) + { + if (i >= 9.99 && i < 99.9) + { + nearest = std::round(i); + result.emplace_back(nearest, std::to_string(nearest).substr(0, 2)); + } + else if (i >= 0.099) + { // also covers numbers above 100 + nearest = std::round(i * 10) / 10; + result.emplace_back(nearest, std::to_string(nearest).substr(0, 3)); + } + else if (i >= 0.0099) + { + nearest = std::round(i * 1000) / 1000; + result.emplace_back(nearest, std::to_string(nearest).substr(0, 4)); + } + else if (i >= 0.00099) + { + nearest = std::round(i * 10000) / 10000; + result.emplace_back(nearest, std::to_string(nearest).substr(1, 4)); + } + else if (i > -0.01 && i < 0.01) + { + result.emplace_back(i, "0"); // an exception, zero is short.. + } + } + } + return result; +} + + +// Periodic update is called by LMMS. +void SaSpectrumView::periodicUpdate() +{ + // check if the widget is visible; if it is not, processing can be paused + m_processor->setSpectrumActive(isVisible()); + // tell Qt it is time for repaint + update(); +} + + +// Handle mouse input: set new cursor position. +void SaSpectrumView::mouseMoveEvent(QMouseEvent *event) +{ + m_cursor = event->pos(); +} + +void SaSpectrumView::mousePressEvent(QMouseEvent *event) +{ + m_cursor = event->pos(); +} + + +// Handle resize event: rebuild grid and labels +void SaSpectrumView::resizeEvent(QResizeEvent *event) +{ + // frequency does not change density with size + // amplitude does: rebuild labels + m_logAmpTics = makeLogAmpTics(m_processor->getAmpRangeMin(), m_processor->getAmpRangeMax()); + m_linearAmpTics = makeLinearAmpTics(m_processor->getAmpRangeMin(), m_processor->getAmpRangeMax()); +} + diff --git a/plugins/SpectrumAnalyzer/SaSpectrumView.h b/plugins/SpectrumAnalyzer/SaSpectrumView.h new file mode 100644 index 000000000..0db5852e1 --- /dev/null +++ b/plugins/SpectrumAnalyzer/SaSpectrumView.h @@ -0,0 +1,126 @@ +/* SaSpectrumView.h - declaration of SaSpectrumView class. + * + * Copyright (c) 2019 Martin Pavelek + * + * Based partially on Eq plugin code, + * Copyright (c) 2014 David French + * + * 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 SASPECTRUMVIEW_H +#define SASPECTRUMVIEW_H + +#include +#include +#include +#include + +class QMouseEvent; +class QPainter; +class SaControls; +class SaProcessor; + +//! Widget that displays a spectrum curve and frequency / amplitude grid +class SaSpectrumView : public QWidget +{ + Q_OBJECT +public: + explicit SaSpectrumView(SaControls *controls, SaProcessor *processor, QWidget *_parent = 0); + virtual ~SaSpectrumView() {} + + QSize sizeHint() const override {return QSize(400, 200);} + +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(); + +private: + const SaControls *m_controls; + SaProcessor *m_processor; + + // grid labels (position, label) and methods to generate them + std::vector> m_logFreqTics; // 10-20-50... Hz + std::vector> m_linearFreqTics; // 2k-4k-6k... Hz + std::vector> m_logAmpTics; // dB + std::vector> m_linearAmpTics; // 0..1 + + std::vector> makeLogFreqTics(int low, int high); + std::vector> makeLinearFreqTics(int low, int high); + std::vector> makeLogAmpTics(int low, int high); + std::vector> makeLinearAmpTics(int low, int high); + + // currently selected ranges (see SaControls.h for enum definitions) + int m_freqRangeIndex; + int m_ampRangeIndex; + + // draw the grid and all labels based on selected ranges + void drawGrid(QPainter &painter); + + // local buffers for frequency bin values and a method to update them + // (mainly needed for averaging and to keep track of peak values) + std::vector m_displayBufferL; + std::vector m_displayBufferR; + std::vector m_peakBufferL; + std::vector m_peakBufferR; + void updateBuffers(float *spectrum, float *displayBuffer, float *peakBuffer); + + // final paths to be drawn by QPainter and methods to build them + QPainterPath m_pathL; + QPainterPath m_pathR; + QPainterPath m_pathPeakL; + QPainterPath m_pathPeakR; + void refreshPaths(); + QPainterPath makePath(std::vector &displayBuffer, float resolution); + + // helper variables for path drawing + float m_decaySum; // indicates if there is anything left to draw + 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; + void drawCursor(QPainter &painter); + + // wrappers for most used SaProcessor conversion helpers + // (to make local code more readable) + float binToFreq(unsigned int bin_index); + float freqToXPixel(float frequency, unsigned int width); + float ampToYPixel(float amplitude, unsigned int height); + + // current boundaries for drawing + unsigned int m_displayTop; + unsigned int m_displayBottom; + unsigned int m_displayLeft; + unsigned int m_displayRight; + unsigned int m_displayWidth; +}; +#endif // SASPECTRUMVIEW_H + diff --git a/plugins/SpectrumAnalyzer/SaWaterfallView.cpp b/plugins/SpectrumAnalyzer/SaWaterfallView.cpp new file mode 100644 index 000000000..617e80b2c --- /dev/null +++ b/plugins/SpectrumAnalyzer/SaWaterfallView.cpp @@ -0,0 +1,230 @@ +/* SaWaterfallViewView.cpp - implementation of SaWaterfallViewView class. + * + * 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. + * + */ + +#include "SaWaterfallView.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "EffectControlDialog.h" +#include "GuiApplication.h" +#include "MainWindow.h" +#include "SaProcessor.h" + + +SaWaterfallView::SaWaterfallView(SaControls *controls, SaProcessor *processor, QWidget *_parent) : + QWidget(_parent), + m_controls(controls), + m_processor(processor) +{ + m_controlDialog = (EffectControlDialog*) _parent; + setMinimumSize(300, 150); + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + + connect(gui->mainWindow(), SIGNAL(periodicUpdate()), this, SLOT(periodicUpdate())); + + m_timeTics = makeTimeTics(); + m_oldTimePerLine = (float)m_processor->m_inBlockSize / m_processor->getSampleRate(); +} + + +// Compose and draw all the content; called by Qt. +// Not as performance sensitive as SaSpectrumView, most of the processing is +// done directly in SaProcessor. +void SaWaterfallView::paintEvent(QPaintEvent *event) +{ + #ifdef SA_DEBUG + int start_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; + float label_width = 20; + float label_height = 16; + float margin = 2; + + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing, true); + + // check if time labels need to be rebuilt + if ((float)m_processor->m_inBlockSize / m_processor->getSampleRate() != m_oldTimePerLine) + { + m_timeTics = makeTimeTics(); + m_oldTimePerLine = (float)m_processor->m_inBlockSize / m_processor->getSampleRate(); + } + + // print time labels + float pos = 0; + painter.setPen(QPen(m_controls->m_colorLabels, 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + for (auto & line: m_timeTics) + { + pos = timeToYPixel(line.first, displayBottom); + // 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, + label_width, label_height, Qt::AlignRight | Qt::AlignTop | Qt::TextDontClip, + QString(line.second.c_str())); + painter.drawText(displayRight + margin, 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) + { + painter.drawText(displayLeft - label_width - margin, 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, + 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, + label_width, label_height, Qt::AlignRight | Qt::AlignVCenter | Qt::TextDontClip, + QString(line.second.c_str())); + painter.drawText(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) + { + 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)); + lock.unlock(); + } + else + { + painter.fillRect(displayLeft, displayTop, displayWidth, displayBottom, QColor(0,0,0)); + } + + // 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); + + #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; + 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())); + #endif +} + + +// 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()); + + return pixels_per_line * time / seconds_per_line; +} + + +// Generate labels for linear time scale. +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()); + + // set increment so that about 8 tics are generated + float increment = std::round(10 * limit / 7) / 10; + + // NOTE: labels positions are rounded to match the (rounded) label value + for (i = 0; i <= limit; i += increment) + { + if (i < 10) + { + result.emplace_back(std::round(i * 10) / 10, std::to_string(std::round(i * 10) / 10).substr(0, 3)); + } + else + { + result.emplace_back(std::round(i), std::to_string(std::round(i)).substr(0, 2)); + } + } + return result; +} + + +// Periodically trigger repaint and check if the widget is visible. +// If it is not, stop drawing and inform the processor. +void SaWaterfallView::periodicUpdate() +{ + m_processor->setWaterfallActive(isVisible()); + if (isVisible()) {update();} +} + + +// Adjust window size and widget visibility when waterfall is enabled or disabbled. +void SaWaterfallView::updateVisibility() +{ + // get container of the control dialog to be resized if needed + QWidget *subWindow = m_controlDialog->parentWidget(); + + + 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(); + + setVisible(true); + + // increase window size if it is too small + if (subWindow->size().height() < m_controlDialog->sizeHint().height()) + { + subWindow->resize(subWindow->size().width(), m_controlDialog->sizeHint().height()); + } + } + else + { + setVisible(false); + // decrease window size only if it does not violate sizeHint + subWindow->resize(subWindow->size().width(), m_controlDialog->sizeHint().height()); + } +} + diff --git a/plugins/SpectrumAnalyzer/SaWaterfallView.h b/plugins/SpectrumAnalyzer/SaWaterfallView.h new file mode 100644 index 000000000..0e104c0a1 --- /dev/null +++ b/plugins/SpectrumAnalyzer/SaWaterfallView.h @@ -0,0 +1,66 @@ +/* SaWaterfallView.h - declaration of SaWaterfallView class. + * + * 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 SAWATERFALLVIEW_H +#define SAWATERFALLVIEW_H + +#include +#include +#include +#include +#include + +#include "SaControls.h" +#include "SaProcessor.h" + + +// Widget that displays a spectrum waterfall (spectrogram) and time labels. +class SaWaterfallView : public QWidget +{ + Q_OBJECT +public: + explicit SaWaterfallView(SaControls *controls, SaProcessor *processor, QWidget *_parent = 0); + virtual ~SaWaterfallView() {} + + QSize sizeHint() const override {return QSize(400, 350);} + + // Check if waterfall should be displayed and adjust window size if needed. + void updateVisibility(); + +protected: + void paintEvent(QPaintEvent *event) override; + +private slots: + void periodicUpdate(); + +private: + const SaControls *m_controls; + SaProcessor *m_processor; + const EffectControlDialog *m_controlDialog; + + // Methods and data used to make time labels + float m_oldTimePerLine; + float timeToYPixel(float time, int height); + std::vector> makeTimeTics(); + std::vector> m_timeTics; // 0..n (s) +}; +#endif // SAWATERFALLVIEW_H diff --git a/plugins/SpectrumAnalyzer/SpectrumAnalyzer.cpp b/plugins/SpectrumAnalyzer/SpectrumAnalyzer.cpp deleted file mode 100644 index f07fa7f45..000000000 --- a/plugins/SpectrumAnalyzer/SpectrumAnalyzer.cpp +++ /dev/null @@ -1,172 +0,0 @@ -/* - * SpectrumAnalyzer.cpp - spectrum analyzer effect plugin - * - * Copyright (c) 2008-2014 Tobias Doerffel - * - * 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. - * - */ - -#include "SpectrumAnalyzer.h" - -#include "embed.h" - - -extern "C" -{ - -Plugin::Descriptor PLUGIN_EXPORT spectrumanalyzer_plugin_descriptor = -{ - STRINGIFY( PLUGIN_NAME ), - "Spectrum Analyzer", - QT_TRANSLATE_NOOP( "pluginBrowser", "Graphical spectrum analyzer plugin" ), - "Tobias Doerffel ", - 0x0100, - Plugin::Effect, - new PluginPixmapLoader(), - NULL, - NULL -} ; - -} - - - -SpectrumAnalyzer::SpectrumAnalyzer( Model * _parent, - const Descriptor::SubPluginFeatures::Key * _key ) : - Effect( &spectrumanalyzer_plugin_descriptor, _parent, _key ), - m_saControls( this ), - m_framesFilledUp( 0 ), - m_energy( 0 ) -{ - memset( m_buffer, 0, sizeof( m_buffer ) ); - - m_specBuf = (fftwf_complex *) fftwf_malloc( ( FFT_BUFFER_SIZE + 1 ) * sizeof( fftwf_complex ) ); - m_fftPlan = fftwf_plan_dft_r2c_1d( FFT_BUFFER_SIZE*2, m_buffer, m_specBuf, FFTW_MEASURE ); -} - - - - -SpectrumAnalyzer::~SpectrumAnalyzer() -{ - fftwf_destroy_plan( m_fftPlan ); - fftwf_free( m_specBuf ); -} - - - - -bool SpectrumAnalyzer::processAudioBuffer( sampleFrame* _buf, const fpp_t _frames ) -{ - if( !isEnabled() || !isRunning () ) - { - return false; - } - - if( !m_saControls.isViewVisible() ) - { - return true; - } - - fpp_t f = 0; - if( _frames > FFT_BUFFER_SIZE ) - { - m_framesFilledUp = 0; - f = _frames - FFT_BUFFER_SIZE; - } - - const int cm = m_saControls.m_channelMode.value(); - - switch( cm ) - { - case MergeChannels: - for( ; f < _frames; ++f ) - { - m_buffer[m_framesFilledUp] = - ( _buf[f][0] + _buf[f][1] ) * 0.5; - ++m_framesFilledUp; - } - break; - case LeftChannel: - for( ; f < _frames; ++f ) - { - m_buffer[m_framesFilledUp] = _buf[f][0]; - ++m_framesFilledUp; - } - break; - case RightChannel: - for( ; f < _frames; ++f ) - { - m_buffer[m_framesFilledUp] = _buf[f][1]; - ++m_framesFilledUp; - } - break; - } - - if( m_framesFilledUp < FFT_BUFFER_SIZE ) - { - return isRunning(); - } - - -// hanming( m_buffer, FFT_BUFFER_SIZE, HAMMING ); - - const sample_rate_t sr = Engine::mixer()->processingSampleRate(); - const int LOWEST_FREQ = 0; - const int HIGHEST_FREQ = sr / 2; - - fftwf_execute( m_fftPlan ); - absspec( m_specBuf, m_absSpecBuf, FFT_BUFFER_SIZE+1 ); - if( m_saControls.m_linearSpec.value() ) - { - compressbands( m_absSpecBuf, m_bands, FFT_BUFFER_SIZE+1, - MAX_BANDS, - (int)(LOWEST_FREQ*(FFT_BUFFER_SIZE+1)/(float)(sr/2)), - (int)(HIGHEST_FREQ*(FFT_BUFFER_SIZE+1)/(float)(sr/2))); - m_energy = maximum( m_bands, MAX_BANDS ) / maximum( m_buffer, FFT_BUFFER_SIZE ); - } - else - { - calc13octaveband31( m_absSpecBuf, m_bands, FFT_BUFFER_SIZE+1, sr/2.0 ); - m_energy = signalpower( m_buffer, FFT_BUFFER_SIZE ) / maximum( m_buffer, FFT_BUFFER_SIZE ); - } - - - m_framesFilledUp = 0; - - checkGate( 1 ); - - return isRunning(); -} - - - - - -extern "C" -{ - -// necessary for getting instance out of shared lib -PLUGIN_EXPORT Plugin * lmms_plugin_main( Model* parent, void* data ) -{ - return new SpectrumAnalyzer( parent, static_cast( data ) ); -} - -} - diff --git a/plugins/SpectrumAnalyzer/SpectrumAnalyzer.h b/plugins/SpectrumAnalyzer/SpectrumAnalyzer.h deleted file mode 100644 index c92351176..000000000 --- a/plugins/SpectrumAnalyzer/SpectrumAnalyzer.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * SpectrumAnalyzer.h - spectrum anaylzer effect plugin - * - * Copyright (c) 2008-2014 Tobias Doerffel - * - * 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 _SPECTRUM_ANALYZER_H -#define _SPECTRUM_ANALYZER_H - -#include "Effect.h" -#include "fft_helpers.h" -#include "SpectrumAnalyzerControls.h" - - -const int MAX_BANDS = 249; - - -class SpectrumAnalyzer : public Effect -{ -public: - enum ChannelModes - { - MergeChannels, - LeftChannel, - RightChannel - } ; - - SpectrumAnalyzer( Model * _parent, - const Descriptor::SubPluginFeatures::Key * _key ); - virtual ~SpectrumAnalyzer(); - virtual bool processAudioBuffer( sampleFrame * _buf, - const fpp_t _frames ); - - virtual EffectControls * controls() - { - return( &m_saControls ); - } - - -private: - SpectrumAnalyzerControls m_saControls; - - fftwf_plan m_fftPlan; - - fftwf_complex * m_specBuf; - float m_absSpecBuf[FFT_BUFFER_SIZE+1]; - float m_buffer[FFT_BUFFER_SIZE*2]; - int m_framesFilledUp; - - float m_bands[MAX_BANDS]; - float m_energy; - - friend class SpectrumAnalyzerControls; - friend class SpectrumView; - -} ; - - -#endif diff --git a/plugins/SpectrumAnalyzer/SpectrumAnalyzerControlDialog.cpp b/plugins/SpectrumAnalyzer/SpectrumAnalyzerControlDialog.cpp deleted file mode 100644 index 05b1ed08a..000000000 --- a/plugins/SpectrumAnalyzer/SpectrumAnalyzerControlDialog.cpp +++ /dev/null @@ -1,194 +0,0 @@ -/* - * SpectrumAnalyzerControlDialog.cpp - view for spectrum analyzer - * - * Copyright (c) 2008-2014 Tobias Doerffel - * - * 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. - * - */ - -#include - -#include -#include - -#include "SpectrumAnalyzer.h" -#include "MainWindow.h" -#include "GuiApplication.h" -#include "LedCheckbox.h" -#include "embed.h" - - -static inline void darken( QImage& img, int x, int y, int w, int h ) -{ - int imgWidth = img.width(); - QRgb * base = ( (QRgb *) img.bits() ) + y*imgWidth + x; - for( int y = 0; y < h; ++y ) - { - QRgb * d = base + y*imgWidth; - for( int x = 0; x < w; ++x ) - { - // shift each color component by 1 bit and set alpha - // to 0xff - d[x] = ( ( d[x] >> 1 ) & 0x7f7f7f7f ) | 0xff000000; - } - } -} - - - -class SpectrumView : public QWidget -{ -public: - SpectrumView( SpectrumAnalyzer* s, QWidget * _parent ) : - QWidget( _parent ), - m_sa( s ), - m_backgroundPlain( PLUGIN_NAME::getIconPixmap( "spectrum_background_plain" ).toImage() ), - m_background( PLUGIN_NAME::getIconPixmap( "spectrum_background" ).toImage() ) - { - setFixedSize( 249, 151 ); - connect( gui->mainWindow(), SIGNAL( periodicUpdate() ), this, SLOT( update() ) ); - setAttribute( Qt::WA_OpaquePaintEvent, true ); - } - - virtual ~SpectrumView() - { - } - - virtual void paintEvent( QPaintEvent* event ) - { - QPainter p( this ); - QImage i = m_sa->m_saControls.m_linearSpec.value() ? - m_backgroundPlain : m_background; - const float e = m_sa->m_energy; - if( e <= 0 ) - { - darken( i, 0, 0, i.width(), i.height() ); - p.drawImage( 0, 0, i ); - return; - } - - const bool lin_y = m_sa->m_saControls.m_linearYAxis.value(); - float * b = m_sa->m_bands; - const int LOWER_Y = -60; // dB - int h; - const int fh = height(); - if( m_sa->m_saControls.m_linearSpec.value() ) - { - if( lin_y ) - { - for( int x = 0; x < MAX_BANDS; ++x, ++b ) - { - h = fh * 2.0 / 3.0 * (*b / e ); - if( h < 0 ) h = 0; else if( h >= fh ) continue; - darken( i, x, 0, 1, fh-h ); - } - } - else - { - for( int x = 0; x < MAX_BANDS; ++x, ++b ) - { - h = (int)( fh * 2.0 / 3.0 * (20*(log10( *b / e ) ) - LOWER_Y ) / (-LOWER_Y ) ); - if( h < 0 ) h = 0; else if( h >= fh ) continue; - darken( i, x, 0, 1, fh-h ); - } - } - } - else - { - if( lin_y ) - { - for( int x = 0; x < 31; ++x, ++b ) - { - h = fh * 2.0 / 3.0 * ( 1.2 * *b / e ); - if( h < 0 ) h = 0; else if( h >= fh ) continue; else h = ( h / 3 ) * 3; - darken( i, x*8, 0, 8, fh-h ); - } - } - else - { - for( int x = 0; x < 31; ++x, ++b ) - { - h = (int)( fh * 2.0 / 3.0 * (20*(log10( *b / e ) ) - LOWER_Y ) / (-LOWER_Y ) ); - if( h < 0 ) h = 0; else if( h >= fh ) continue; else h = ( h / 3 ) * 3; - darken( i, x*8, 0, 8, fh-h ); - } - } - darken( i, 31*8, 0, 1, fh ); - } - p.drawImage( 0, 0, i ); - } - - -private: - SpectrumAnalyzer * m_sa; - QImage m_backgroundPlain; - QImage m_background; - -} ; - - - - -SpectrumAnalyzerControlDialog::SpectrumAnalyzerControlDialog( SpectrumAnalyzerControls* controls ) : - EffectControlDialog( controls ), - m_controls( controls ), - m_logXAxis( PLUGIN_NAME::getIconPixmap( "log_x_axis" ) ), - m_logYAxis( PLUGIN_NAME::getIconPixmap( "log_y_axis" ) ) -{ - setAutoFillBackground( true ); - QPalette pal; - pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap( "background" ) ); - setFixedSize( 293, 205 ); - setPalette( pal ); -/* QVBoxLayout * l = new QVBoxLayout( this );*/ - SpectrumView* v = new SpectrumView( controls->m_effect, this ); - v->move( 34, 10 ); - - LedCheckBox * lin_spec = new LedCheckBox( tr( "Linear spectrum" ), this ); - lin_spec->move( 32, 182 ); - lin_spec->setModel( &controls->m_linearSpec ); - - LedCheckBox * lin_y = new LedCheckBox( tr( "Linear Y axis" ), this ); - lin_y->move( 137, 182 ); - lin_y->setModel( &controls->m_linearYAxis ); - - connect( &controls->m_linearSpec, SIGNAL( dataChanged() ), this, SLOT( update() ) ); - connect( &controls->m_linearYAxis, SIGNAL( dataChanged() ), this, SLOT( update() ) ); -/* l->addWidget( v ); - l->addWidget( lin_spec ); - l->addWidget( lin_y );*/ - -} - - -void SpectrumAnalyzerControlDialog::paintEvent( QPaintEvent * ) -{ - QPainter p( this ); - - if( !m_controls->m_linearSpec.value() ) - { - p.drawPixmap( 33, 165, m_logXAxis ); - } - - if( !m_controls->m_linearYAxis.value() ) - { - p.drawPixmap( 10, 29, m_logYAxis); - } - -} diff --git a/plugins/SpectrumAnalyzer/SpectrumAnalyzerControls.cpp b/plugins/SpectrumAnalyzer/SpectrumAnalyzerControls.cpp deleted file mode 100644 index 4a59b3c0a..000000000 --- a/plugins/SpectrumAnalyzer/SpectrumAnalyzerControls.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - * SpectrumAnalyzerControls.cpp - controls for spectrum analyzer - * - * Copyright (c) 2008-2014 Tobias Doerffel - * - * 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. - * - */ - - -#include "SpectrumAnalyzer.h" -#include "SpectrumAnalyzerControls.h" - - - -SpectrumAnalyzerControls::SpectrumAnalyzerControls( SpectrumAnalyzer* effect ) : - EffectControls( effect ), - m_effect( effect ), - m_linearSpec( false, this, tr( "Linear spectrum" ) ), - m_linearYAxis( false, this, tr( "Linear Y axis" ) ), - m_channelMode( SpectrumAnalyzer::MergeChannels, - SpectrumAnalyzer::MergeChannels, - SpectrumAnalyzer::RightChannel, - this, tr( "Channel mode" ) ) -{ -} - - - - -void SpectrumAnalyzerControls::loadSettings( const QDomElement & _this ) -{ -} - - - - -void SpectrumAnalyzerControls::saveSettings( QDomDocument & _doc, - QDomElement & _this ) -{ -} - - - - - diff --git a/plugins/SpectrumAnalyzer/SpectrumAnalyzerControls.h b/plugins/SpectrumAnalyzer/SpectrumAnalyzerControls.h deleted file mode 100644 index e46407863..000000000 --- a/plugins/SpectrumAnalyzer/SpectrumAnalyzerControls.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * SpectrumAnalyzerControls.h - controls for spectrum-analyzer - * - * Copyright (c) 2008-2014 Tobias Doerffel - * - * 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 SPECTRUM_ANALYZER_CONTROLS_H -#define SPECTRUM_ANALYZER_CONTROLS_H - -#include "EffectControls.h" -#include "SpectrumAnalyzerControlDialog.h" -#include "Knob.h" - - -class SpectrumAnalyzer; - - -class SpectrumAnalyzerControls : public EffectControls -{ - Q_OBJECT -public: - SpectrumAnalyzerControls( SpectrumAnalyzer* effect ); - virtual ~SpectrumAnalyzerControls() - { - } - - virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent ); - virtual void loadSettings( const QDomElement & _this ); - inline virtual QString nodeName() const - { - return "spectrumanaylzercontrols"; - } - - virtual int controlCount() - { - return 1; - } - - virtual EffectControlDialog * createView() - { - return new SpectrumAnalyzerControlDialog( this ); - } - - -private: - SpectrumAnalyzer* m_effect; - BoolModel m_linearSpec; - BoolModel m_linearYAxis; - IntModel m_channelMode; - - friend class SpectrumAnalyzer; - friend class SpectrumAnalyzerControlDialog; - friend class SpectrumView; - -} ; - -#endif diff --git a/plugins/SpectrumAnalyzer/background.png b/plugins/SpectrumAnalyzer/background.png deleted file mode 100644 index e375f7d34..000000000 Binary files a/plugins/SpectrumAnalyzer/background.png and /dev/null differ diff --git a/plugins/SpectrumAnalyzer/block_size.svg b/plugins/SpectrumAnalyzer/block_size.svg new file mode 100644 index 000000000..e9c4806ec --- /dev/null +++ b/plugins/SpectrumAnalyzer/block_size.svg @@ -0,0 +1,273 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/plugins/SpectrumAnalyzer/freeze.svg b/plugins/SpectrumAnalyzer/freeze.svg new file mode 100644 index 000000000..4c9a43c12 --- /dev/null +++ b/plugins/SpectrumAnalyzer/freeze.svg @@ -0,0 +1,296 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/SpectrumAnalyzer/freeze_off.svg b/plugins/SpectrumAnalyzer/freeze_off.svg new file mode 100644 index 000000000..b6353d7a7 --- /dev/null +++ b/plugins/SpectrumAnalyzer/freeze_off.svg @@ -0,0 +1,297 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/SpectrumAnalyzer/log_x_axis.png b/plugins/SpectrumAnalyzer/log_x_axis.png deleted file mode 100644 index 97c5e729d..000000000 Binary files a/plugins/SpectrumAnalyzer/log_x_axis.png and /dev/null differ diff --git a/plugins/SpectrumAnalyzer/log_y_axis.png b/plugins/SpectrumAnalyzer/log_y_axis.png deleted file mode 100644 index e20d27001..000000000 Binary files a/plugins/SpectrumAnalyzer/log_y_axis.png and /dev/null differ diff --git a/plugins/SpectrumAnalyzer/pause.svg b/plugins/SpectrumAnalyzer/pause.svg new file mode 100644 index 000000000..d28a93aa5 --- /dev/null +++ b/plugins/SpectrumAnalyzer/pause.svg @@ -0,0 +1,220 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/plugins/SpectrumAnalyzer/play.svg b/plugins/SpectrumAnalyzer/play.svg new file mode 100644 index 000000000..eb3178284 --- /dev/null +++ b/plugins/SpectrumAnalyzer/play.svg @@ -0,0 +1,219 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/plugins/SpectrumAnalyzer/spectrum_background.png b/plugins/SpectrumAnalyzer/spectrum_background.png deleted file mode 100644 index b65491bc3..000000000 Binary files a/plugins/SpectrumAnalyzer/spectrum_background.png and /dev/null differ diff --git a/plugins/SpectrumAnalyzer/spectrum_background_plain.png b/plugins/SpectrumAnalyzer/spectrum_background_plain.png deleted file mode 100644 index ba9bcd1c8..000000000 Binary files a/plugins/SpectrumAnalyzer/spectrum_background_plain.png and /dev/null differ diff --git a/plugins/SpectrumAnalyzer/window.svg b/plugins/SpectrumAnalyzer/window.svg new file mode 100644 index 000000000..5d0bd7dbd --- /dev/null +++ b/plugins/SpectrumAnalyzer/window.svg @@ -0,0 +1,232 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/plugins/SpectrumAnalyzer/x_linear.svg b/plugins/SpectrumAnalyzer/x_linear.svg new file mode 100644 index 000000000..cef788670 --- /dev/null +++ b/plugins/SpectrumAnalyzer/x_linear.svg @@ -0,0 +1,242 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/plugins/SpectrumAnalyzer/x_log.svg b/plugins/SpectrumAnalyzer/x_log.svg new file mode 100644 index 000000000..8b8dc8b5a --- /dev/null +++ b/plugins/SpectrumAnalyzer/x_log.svg @@ -0,0 +1,240 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/plugins/SpectrumAnalyzer/y_linear.svg b/plugins/SpectrumAnalyzer/y_linear.svg new file mode 100644 index 000000000..69c39bb05 --- /dev/null +++ b/plugins/SpectrumAnalyzer/y_linear.svg @@ -0,0 +1,240 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/plugins/SpectrumAnalyzer/y_log.svg b/plugins/SpectrumAnalyzer/y_log.svg new file mode 100644 index 000000000..645e09e5a --- /dev/null +++ b/plugins/SpectrumAnalyzer/y_log.svg @@ -0,0 +1,240 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/plugins/VstEffect/CMakeLists.txt b/plugins/VstEffect/CMakeLists.txt index ec05a14ea..68ef141d9 100644 --- a/plugins/VstEffect/CMakeLists.txt +++ b/plugins/VstEffect/CMakeLists.txt @@ -11,9 +11,7 @@ ELSE() ENDIF() BUILD_PLUGIN(vsteffect VstEffect.cpp VstEffectControls.cpp VstEffectControlDialog.cpp VstSubPluginFeatures.cpp VstEffect.h VstEffectControls.h VstEffectControlDialog.h VstSubPluginFeatures.h MOCFILES VstEffectControlDialog.h VstEffectControls.h EMBEDDED_RESOURCES *.png) -SET_TARGET_PROPERTIES(vsteffect PROPERTIES COMPILE_FLAGS "-Wno-attributes") -TARGET_LINK_LIBRARIES(vsteffect -lvstbase) -ADD_DEPENDENCIES(vsteffect vstbase) +TARGET_LINK_LIBRARIES(vsteffect vstbase) ENDIF(LMMS_SUPPORT_VST) diff --git a/plugins/VstEffect/VstEffect.cpp b/plugins/VstEffect/VstEffect.cpp index ed05a82a0..80f209a7b 100644 --- a/plugins/VstEffect/VstEffect.cpp +++ b/plugins/VstEffect/VstEffect.cpp @@ -32,7 +32,7 @@ #include "VstSubPluginFeatures.h" #include "embed.h" - +#include "plugin_export.h" extern "C" { @@ -95,9 +95,11 @@ bool VstEffect::processAudioBuffer( sampleFrame * _buf, const fpp_t _frames ) sampleFrame * buf = new sampleFrame[_frames]; #endif memcpy( buf, _buf, sizeof( sampleFrame ) * _frames ); - m_pluginMutex.lock(); - m_plugin->process( buf, buf ); - m_pluginMutex.unlock(); + if (m_pluginMutex.tryLock(Engine::getSong()->isExporting() ? -1 : 0)) + { + m_plugin->process( buf, buf ); + m_pluginMutex.unlock(); + } double out_sum = 0.0; const float w = wetLevel(); @@ -143,9 +145,6 @@ void VstEffect::openPlugin( const QString & _plugin ) return; } - VstPlugin::connect( Engine::getSong(), SIGNAL( tempoChanged( bpm_t ) ), m_plugin.data(), SLOT( setTempo( bpm_t ) ) ); - m_plugin->setTempo( Engine::getSong()->getTempo() ); - delete tf; m_key.attributes["file"] = _plugin; diff --git a/plugins/VstEffect/VstEffectControlDialog.cpp b/plugins/VstEffect/VstEffectControlDialog.cpp index 678bb9136..156eaae01 100644 --- a/plugins/VstEffect/VstEffectControlDialog.cpp +++ b/plugins/VstEffect/VstEffectControlDialog.cpp @@ -41,10 +41,10 @@ #include #include - VstEffectControlDialog::VstEffectControlDialog( VstEffectControls * _ctl ) : EffectControlDialog( _ctl ), m_pluginWidget( NULL ), + m_plugin( NULL ), tbLabel( NULL ) { @@ -62,24 +62,18 @@ VstEffectControlDialog::VstEffectControlDialog( VstEffectControls * _ctl ) : embed_vst = m_plugin->embedMethod() != "none"; if (embed_vst) { - m_plugin->createUI( nullptr, true ); - m_pluginWidget = m_plugin->pluginWidget( false ); - -#ifdef LMMS_BUILD_WIN32 - if( !m_pluginWidget ) - { - m_pluginWidget = m_plugin->pluginWidget( false ); + if (m_plugin->hasEditor() && ! m_plugin->pluginWidget()) { + m_plugin->createUI(this); } -#endif - + m_pluginWidget = m_plugin->pluginWidget(); } } - if ( m_plugin && (!embed_vst || m_pluginWidget) ) + if (m_plugin) { setWindowTitle( m_plugin->name() ); - QPushButton * btn = new QPushButton( tr( "Show/hide" ) ); + QPushButton * btn = new QPushButton( tr( "Show/hide" )); if (embed_vst) { btn->setCheckable( true ); @@ -87,14 +81,15 @@ VstEffectControlDialog::VstEffectControlDialog( VstEffectControls * _ctl ) : connect( btn, SIGNAL( toggled( bool ) ), SLOT( togglePluginUI( bool ) ) ); } else { - connect( btn, SIGNAL( clicked( bool ) ), - SLOT( togglePluginUI( bool ) ) ); + connect( btn, SIGNAL( clicked() ), + m_plugin.data(), SLOT( toggleUI() ) ); } btn->setMinimumWidth( 78 ); btn->setMaximumWidth( 78 ); btn->setMinimumHeight( 24 ); btn->setMaximumHeight( 24 ); + m_togglePluginButton = btn; m_managePluginButton = new PixmapButton( this, "" ); m_managePluginButton->setCheckable( false ); @@ -206,7 +201,7 @@ VstEffectControlDialog::VstEffectControlDialog( VstEffectControls * _ctl ) : int newSize = 0; - if (embed_vst) { + if (m_pluginWidget) { newSize = m_pluginWidget->width() + 20; } newSize = std::max(newSize, 250); @@ -222,7 +217,7 @@ VstEffectControlDialog::VstEffectControlDialog( VstEffectControls * _ctl ) : l->addItem( new QSpacerItem( newSize - 20, 30, QSizePolicy::Fixed, QSizePolicy::Fixed ), 1, 0 ); l->addWidget( resize, 2, 0, 1, 1, Qt::AlignCenter ); - if (embed_vst) { + if (m_pluginWidget) { l->addWidget( m_pluginWidget, 3, 0, 1, 1, Qt::AlignCenter ); } l->setRowStretch( 5, 1 ); @@ -261,12 +256,26 @@ void VstEffectControlDialog::paintEvent( QPaintEvent * ) } } +void VstEffectControlDialog::showEvent(QShowEvent *_se) +{ + EffectControlDialog::showEvent( _se ); + // Workaround for a (unexplained) bug where on project-load the effect + // control window has size 0 and would only restore to the proper size upon + // moving the window or interacting with it. + if (parentWidget()) { + parentWidget()->adjustSize(); + } +} + VstEffectControlDialog::~VstEffectControlDialog() { - //delete m_pluginWidget; + if (m_pluginWidget && layout()) { + layout()->removeWidget(m_pluginWidget); + m_pluginWidget->setParent(nullptr); + } } @@ -278,6 +287,14 @@ void VstEffectControlDialog::togglePluginUI( bool checked ) return; } - m_plugin->toggleUI(); + if ( m_togglePluginButton->isChecked() != checked ) { + m_togglePluginButton->setChecked( checked ); + } + + if ( checked ) { + m_plugin->showUI(); + } else { + m_plugin->hideUI(); + } } diff --git a/plugins/VstEffect/VstEffectControlDialog.h b/plugins/VstEffect/VstEffectControlDialog.h index ddbbef878..930f514c9 100644 --- a/plugins/VstEffect/VstEffectControlDialog.h +++ b/plugins/VstEffect/VstEffectControlDialog.h @@ -49,11 +49,13 @@ public: virtual ~VstEffectControlDialog(); protected: - virtual void paintEvent( QPaintEvent * _pe ); + void paintEvent( QPaintEvent * _pe ) override; + void showEvent( QShowEvent* _se ) override; private: QWidget * m_pluginWidget; + QPushButton * m_togglePluginButton; PixmapButton * m_openPresetButton; PixmapButton * m_rolLPresetButton; PixmapButton * m_rolRPresetButton; @@ -64,7 +66,7 @@ private: QLabel * tbLabel; -private slots: +public slots: void togglePluginUI( bool checked ); } ; diff --git a/plugins/VstEffect/VstEffectControls.cpp b/plugins/VstEffect/VstEffectControls.cpp index 60f0e7b82..a0f97ce71 100644 --- a/plugins/VstEffect/VstEffectControls.cpp +++ b/plugins/VstEffect/VstEffectControls.cpp @@ -27,6 +27,7 @@ #include "VstEffectControls.h" #include "VstEffect.h" +#include "LocaleHelper.h" #include "MainWindow.h" #include "GuiApplication.h" #include @@ -40,7 +41,8 @@ VstEffectControls::VstEffectControls( VstEffect * _eff ) : m_subWindow( NULL ), knobFModel( NULL ), ctrHandle( NULL ), - lastPosInMenu (0) + lastPosInMenu (0), + m_vstGuiVisible ( true ) // m_presetLabel ( NULL ) { } @@ -64,6 +66,8 @@ void VstEffectControls::loadSettings( const QDomElement & _this ) m_effect->m_pluginMutex.lock(); if( m_effect->m_plugin != NULL ) { + m_vstGuiVisible = _this.attribute( "guivisible" ).toInt(); + m_effect->m_plugin->loadSettings( _this ); const QMap & dump = m_effect->m_plugin->parameterDump(); @@ -82,11 +86,12 @@ void VstEffectControls::loadSettings( const QDomElement & _this ) if( !( knobFModel[ i ]->isAutomated() || knobFModel[ i ]->controllerConnection() ) ) { - knobFModel[ i ]->setValue( (s_dumpValues.at( 2 ) ).toFloat() ); - knobFModel[ i ]->setInitValue( (s_dumpValues.at( 2 ) ).toFloat() ); + knobFModel[ i ]->setValue(LocaleHelper::toFloat(s_dumpValues.at(2))); + knobFModel[ i ]->setInitValue(LocaleHelper::toFloat(s_dumpValues.at(2))); } - connect( knobFModel[i], SIGNAL( dataChanged() ), this, SLOT( setParameter() ) ); + connect( knobFModel[i], &FloatModel::dataChanged, this, + [this, i]() { setParameter( knobFModel[i] ); }, Qt::DirectConnection); } } @@ -96,10 +101,8 @@ void VstEffectControls::loadSettings( const QDomElement & _this ) -void VstEffectControls::setParameter( void ) +void VstEffectControls::setParameter( Model * action ) { - - Model *action = qobject_cast(sender()); int knobUNID = action->displayName().toInt(); if ( m_effect->m_plugin != NULL ) { @@ -138,8 +141,16 @@ void VstEffectControls::saveSettings( QDomDocument & _doc, QDomElement & _this ) int VstEffectControls::controlCount() { - return m_effect->m_plugin != NULL && - m_effect->m_plugin->hasEditor() ? 1 : 0; + return m_effect->m_plugin != NULL ? 1 : 0; +} + + + +EffectControlDialog *VstEffectControls::createView() +{ + auto dialog = new VstEffectControlDialog( this ); + dialog->togglePluginUI( m_vstGuiVisible ); + return dialog; } @@ -198,18 +209,16 @@ void VstEffectControls::updateMenu( void ) QMenu * to_menu = m_selPresetButton->menu(); to_menu->clear(); - QAction *presetActions[list1.size()]; - for (int i = 0; i < list1.size(); i++) { - presetActions[i] = new QAction(this); - connect(presetActions[i], SIGNAL(triggered()), this, SLOT(selPreset())); + QAction* presetAction = new QAction(this); + connect(presetAction, SIGNAL(triggered()), this, SLOT(selPreset())); - presetActions[i]->setText(QString("%1. %2").arg(QString::number(i+1), list1.at(i))); - presetActions[i]->setData(i); + presetAction->setText(QString("%1. %2").arg(QString::number(i+1), list1.at(i))); + presetAction->setData(i); if (i == lastPosInMenu) { - presetActions[i]->setIcon(embed::getIconPixmap( "sample_file", 16, 16 )); - } else presetActions[i]->setIcon(embed::getIconPixmap( "edit_copy", 16, 16 )); - to_menu->addAction( presetActions[i] ); + presetAction->setIcon(embed::getIconPixmap( "sample_file", 16, 16 )); + } else presetAction->setIcon(embed::getIconPixmap( "edit_copy", 16, 16 )); + to_menu->addAction( presetAction ); } } @@ -306,7 +315,7 @@ manageVSTEffectView::manageVSTEffectView( VstEffect * _eff, VstEffectControls * m_vi->m_subWindow->setWidget(m_vi->m_scrollArea); m_vi->m_subWindow->setWindowTitle( _eff->m_plugin->name() + tr( " - VST parameter control" ) ); m_vi->m_subWindow->setWindowIcon( PLUGIN_NAME::getIconPixmap( "logo" ) ); - //m_vi->m_subWindow->setAttribute(Qt::WA_DeleteOnClose); + m_vi->m_subWindow->setAttribute(Qt::WA_DeleteOnClose, false); l->setContentsMargins( 20, 10, 10, 10 ); @@ -364,12 +373,14 @@ manageVSTEffectView::manageVSTEffectView( VstEffect * _eff, VstEffectControls * if( !hasKnobModel ) { sprintf( paramStr, "%d", i); - m_vi->knobFModel[ i ] = new FloatModel( ( s_dumpValues.at( 2 ) ).toFloat(), + m_vi->knobFModel[ i ] = new FloatModel( LocaleHelper::toFloat(s_dumpValues.at(2)), 0.0f, 1.0f, 0.01f, _eff, tr( paramStr ) ); } - connect( m_vi->knobFModel[ i ], SIGNAL( dataChanged() ), this, - SLOT( setParameter() ) ); - vstKnobs[ i ] ->setModel( m_vi->knobFModel[ i ] ); + + FloatModel * model = m_vi->knobFModel[i]; + connect( model, &FloatModel::dataChanged, this, + [this, model]() { setParameter( model ); }, Qt::DirectConnection); + vstKnobs[ i ] ->setModel( model ); } int i = 0; @@ -428,7 +439,7 @@ void manageVSTEffectView::syncPlugin( void ) { sprintf( paramStr, "param%d", i ); s_dumpValues = dump[ paramStr ].split( ":" ); - f_value = ( s_dumpValues.at( 2 ) ).toFloat(); + f_value = LocaleHelper::toFloat(s_dumpValues.at(2)); m_vi2->knobFModel[ i ]->setAutomatedValue( f_value ); m_vi2->knobFModel[ i ]->setInitValue( f_value ); } @@ -462,10 +473,8 @@ void manageVSTEffectView::displayAutomatedOnly( void ) -void manageVSTEffectView::setParameter( void ) +void manageVSTEffectView::setParameter( Model * action ) { - - Model *action = qobject_cast(sender()); int knobUNID = action->displayName().toInt(); if ( m_effect->m_plugin != NULL ) { diff --git a/plugins/VstEffect/VstEffectControls.h b/plugins/VstEffect/VstEffectControls.h index 7328f2f42..092669f94 100644 --- a/plugins/VstEffect/VstEffectControls.h +++ b/plugins/VstEffect/VstEffectControls.h @@ -59,10 +59,7 @@ public: virtual int controlCount(); - virtual EffectControlDialog * createView() - { - return new VstEffectControlDialog( this ); - } + virtual EffectControlDialog * createView(); protected slots: @@ -73,7 +70,7 @@ protected slots: void rollPreset( void ); void rolrPreset( void ); void selPreset( void ); - void setParameter( void ); + void setParameter( Model * action ); protected: virtual void paintEvent( QPaintEvent * _pe ); @@ -96,6 +93,7 @@ private: friend class VstEffectControlDialog; friend class manageVSTEffectView; + bool m_vstGuiVisible; } ; @@ -112,7 +110,7 @@ public: protected slots: void syncPlugin( void ); void displayAutomatedOnly( void ); - void setParameter( void ); + void setParameter( Model * action ); void closeWindow(); private: diff --git a/plugins/Xpressive/CMakeLists.txt b/plugins/Xpressive/CMakeLists.txt index 6745c71d5..366381e62 100644 --- a/plugins/Xpressive/CMakeLists.txt +++ b/plugins/Xpressive/CMakeLists.txt @@ -12,6 +12,8 @@ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WERROR_FLAGS} -fexceptions") IF(LMMS_BUILD_WIN32 AND NOT MSVC) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wa,-mbig-obj -Dexprtk_disable_enhanced_features") +ELSEIF(LMMS_BUILD_WIN32 AND MSVC) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj") ENDIF() BUILD_PLUGIN(xpressive diff --git a/plugins/Xpressive/Xpressive.cpp b/plugins/Xpressive/Xpressive.cpp index 8c9aa1532..a80a0ae41 100644 --- a/plugins/Xpressive/Xpressive.cpp +++ b/plugins/Xpressive/Xpressive.cpp @@ -48,12 +48,14 @@ #include "ExprSynth.h" +#include "plugin_export.h" + 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 }; } @@ -255,7 +257,6 @@ public: setCenterPointY(14.5); setInnerRadius(4); setOuterRadius(9); - setOuterColor(QColor(0x519fff)); setTotalAngle(300.0); setLineWidth(3); } @@ -272,17 +273,21 @@ public: XpressiveView::XpressiveView(Instrument * _instrument, QWidget * _parent) : - InstrumentView(_instrument, _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; @@ -291,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); @@ -311,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")); @@ -357,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( @@ -396,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( @@ -413,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:"), ""); @@ -450,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())); @@ -746,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(); @@ -754,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(); @@ -762,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(); @@ -770,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(); @@ -784,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(); @@ -792,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(); @@ -805,8 +817,6 @@ void XpressiveView::usrWaveClicked() { Engine::getSong()->setModified(); } -XpressiveHelpView* XpressiveHelpView::s_instance=0; - QString XpressiveHelpView::s_helpText= "O1, O2 - Two output waves. Panning is controled by PN1 and PN2.
" "W1, W2, W3 - Wave samples evaluated by expression. In these samples, t variable ranges [0,1).
" @@ -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 ); @@ -874,16 +884,11 @@ void XpressiveView::helpClicked() { } -__attribute__((destructor)) static void module_destroy() -{ - XpressiveHelpView::finalize(); -} - extern "C" { // necessary for getting instance out of shared lib -Plugin * PLUGIN_EXPORT lmms_plugin_main(Model *, void * _data) { - return (new Xpressive(static_cast(_data))); +PLUGIN_EXPORT Plugin * lmms_plugin_main(Model *m, void *) { + return (new Xpressive(static_cast(m))); } } diff --git a/plugins/Xpressive/Xpressive.h b/plugins/Xpressive/Xpressive.h index 9d4636ca5..5abee2691 100644 --- a/plugins/Xpressive/Xpressive.h +++ b/plugins/Xpressive/Xpressive.h @@ -139,7 +139,7 @@ private: } ; -class XpressiveView : public InstrumentView +class XpressiveView : public InstrumentViewFixedSize { Q_OBJECT public: @@ -206,22 +206,16 @@ class XpressiveHelpView: public QTextEdit public: static XpressiveHelpView* getInstance() { - if (!s_instance) - { - s_instance = new XpressiveHelpView(); - } - return s_instance; + static XpressiveHelpView instance; + return &instance; } static void finalize() { - if (s_instance) { delete s_instance; } } private: XpressiveHelpView(); - static XpressiveHelpView *s_instance; static QString s_helpText; - }; #endif 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 d5b39acee..1f4e35ad5 100644 Binary files a/plugins/Xpressive/artwork.png and b/plugins/Xpressive/artwork.png differ diff --git a/plugins/Xpressive/help_active.png b/plugins/Xpressive/help_active.png index 4e991ad54..8d8b49d43 100644 Binary files a/plugins/Xpressive/help_active.png and b/plugins/Xpressive/help_active.png differ diff --git a/plugins/Xpressive/help_inactive.png b/plugins/Xpressive/help_inactive.png index 4b77af24f..d08f6d9a7 100644 Binary files a/plugins/Xpressive/help_inactive.png and b/plugins/Xpressive/help_inactive.png differ diff --git a/plugins/Xpressive/logo.png b/plugins/Xpressive/logo.png index 68b613176..555c3f13e 100644 Binary files a/plugins/Xpressive/logo.png and b/plugins/Xpressive/logo.png differ diff --git a/plugins/Xpressive/o1_active.png b/plugins/Xpressive/o1_active.png index 6370769dd..8e31a8322 100644 Binary files a/plugins/Xpressive/o1_active.png and b/plugins/Xpressive/o1_active.png differ diff --git a/plugins/Xpressive/o1_inactive.png b/plugins/Xpressive/o1_inactive.png index 0fd4f8b29..7a6b603e3 100644 Binary files a/plugins/Xpressive/o1_inactive.png and b/plugins/Xpressive/o1_inactive.png differ diff --git a/plugins/Xpressive/o2_active.png b/plugins/Xpressive/o2_active.png index 51897412d..4e3b5f214 100644 Binary files a/plugins/Xpressive/o2_active.png and b/plugins/Xpressive/o2_active.png differ diff --git a/plugins/Xpressive/o2_inactive.png b/plugins/Xpressive/o2_inactive.png index 20158d725..35851d553 100644 Binary files a/plugins/Xpressive/o2_inactive.png and b/plugins/Xpressive/o2_inactive.png differ diff --git a/plugins/Xpressive/w1_active.png b/plugins/Xpressive/w1_active.png index 49a3a2b6e..68d8e9ae0 100644 Binary files a/plugins/Xpressive/w1_active.png and b/plugins/Xpressive/w1_active.png differ diff --git a/plugins/Xpressive/w1_inactive.png b/plugins/Xpressive/w1_inactive.png index 266e4206f..7159b4979 100644 Binary files a/plugins/Xpressive/w1_inactive.png and b/plugins/Xpressive/w1_inactive.png differ diff --git a/plugins/Xpressive/w2_active.png b/plugins/Xpressive/w2_active.png index cd4729949..17d7b53d9 100644 Binary files a/plugins/Xpressive/w2_active.png and b/plugins/Xpressive/w2_active.png differ diff --git a/plugins/Xpressive/w2_inactive.png b/plugins/Xpressive/w2_inactive.png index 8d54929da..412482bb0 100644 Binary files a/plugins/Xpressive/w2_inactive.png and b/plugins/Xpressive/w2_inactive.png differ diff --git a/plugins/Xpressive/w3_active.png b/plugins/Xpressive/w3_active.png index 9e4facb2c..579b997dd 100644 Binary files a/plugins/Xpressive/w3_active.png and b/plugins/Xpressive/w3_active.png differ diff --git a/plugins/Xpressive/w3_inactive.png b/plugins/Xpressive/w3_inactive.png index e5b0bc7d9..d45d8b497 100644 Binary files a/plugins/Xpressive/w3_inactive.png and b/plugins/Xpressive/w3_inactive.png differ diff --git a/plugins/Xpressive/wavegraph.png b/plugins/Xpressive/wavegraph.png index 9d58e8fe7..ea7bc3761 100644 Binary files a/plugins/Xpressive/wavegraph.png and b/plugins/Xpressive/wavegraph.png differ diff --git a/plugins/audio_file_processor/audio_file_processor.cpp b/plugins/audio_file_processor/audio_file_processor.cpp index 5f5f19c9d..7a6eb66ac 100644 --- a/plugins/audio_file_processor/audio_file_processor.cpp +++ b/plugins/audio_file_processor/audio_file_processor.cpp @@ -45,7 +45,7 @@ #include "DataFile.h" #include "embed.h" - +#include "plugin_export.h" extern "C" { @@ -449,7 +449,7 @@ QPixmap * AudioFileProcessorView::s_artwork = NULL; AudioFileProcessorView::AudioFileProcessorView( Instrument * _instrument, QWidget * _parent ) : - InstrumentView( _instrument, _parent ) + InstrumentViewFixedSize( _instrument, _parent ) { if( s_artwork == NULL ) { @@ -505,7 +505,7 @@ AudioFileProcessorView::AudioFileProcessorView( Instrument * _instrument, "loop_pingpong_on" ) ); m_loopPingPongButton->setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "loop_pingpong_off" ) ); - ToolTip::add( m_loopPingPongButton, tr( "Enable loop" ) ); + ToolTip::add( m_loopPingPongButton, tr( "Enable ping-pong loop" ) ); m_loopGroup = new automatableButtonGroup( this ); m_loopGroup->addButton( m_loopOffButton ); @@ -753,6 +753,7 @@ AudioFileProcessorWaveView::AudioFileProcessorWaveView( QWidget * _parent, int _ m_graph.fill( Qt::transparent ); update(); + updateCursor(); } @@ -769,7 +770,7 @@ void AudioFileProcessorWaveView::isPlaying( f_cnt_t _current_frame ) void AudioFileProcessorWaveView::enterEvent( QEvent * _e ) { - QApplication::setOverrideCursor( Qt::OpenHandCursor ); + updateCursor(); } @@ -777,10 +778,7 @@ void AudioFileProcessorWaveView::enterEvent( QEvent * _e ) void AudioFileProcessorWaveView::leaveEvent( QEvent * _e ) { - while( QApplication::overrideCursor() ) - { - QApplication::restoreOverrideCursor(); - } + updateCursor(); } @@ -808,7 +806,7 @@ void AudioFileProcessorWaveView::mousePressEvent( QMouseEvent * _me ) else { m_draggingType = wave; - QApplication::setOverrideCursor( Qt::ClosedHandCursor ); + updateCursor(_me); } } @@ -820,7 +818,7 @@ void AudioFileProcessorWaveView::mouseReleaseEvent( QMouseEvent * _me ) m_isDragging = false; if( m_draggingType == wave ) { - QApplication::restoreOverrideCursor(); + updateCursor(_me); } } @@ -831,22 +829,7 @@ void AudioFileProcessorWaveView::mouseMoveEvent( QMouseEvent * _me ) { if( ! m_isDragging ) { - const bool is_size_cursor = - QApplication::overrideCursor()->shape() == Qt::SizeHorCursor; - - if( isCloseTo( _me->x(), m_startFrameX ) || - isCloseTo( _me->x(), m_endFrameX ) || - isCloseTo( _me->x(), m_loopFrameX ) ) - { - if( ! is_size_cursor ) - { - QApplication::setOverrideCursor( Qt::SizeHorCursor ); - } - } - else if( is_size_cursor ) - { - QApplication::restoreOverrideCursor(); - } + updateCursor(_me); return; } @@ -1219,6 +1202,24 @@ void AudioFileProcessorWaveView::reverse() +void AudioFileProcessorWaveView::updateCursor( QMouseEvent * _me ) +{ + bool const waveIsDragged = m_isDragging && (m_draggingType == wave); + bool const pointerCloseToStartEndOrLoop = (_me != nullptr ) && + ( isCloseTo( _me->x(), m_startFrameX ) || + isCloseTo( _me->x(), m_endFrameX ) || + isCloseTo( _me->x(), m_loopFrameX ) ); + + if( !m_isDragging && pointerCloseToStartEndOrLoop) + setCursor(Qt::SizeHorCursor); + else if( waveIsDragged ) + setCursor(Qt::ClosedHandCursor); + else + setCursor(Qt::OpenHandCursor); +} + + + void AudioFileProcessorWaveView::knob::slideTo( double _v, bool _check_bound ) { @@ -1277,10 +1278,9 @@ extern "C" { // necessary for getting instance out of shared lib -PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *, void * _data ) +PLUGIN_EXPORT Plugin * lmms_plugin_main(Model * model, void *) { - return new audioFileProcessor( - static_cast( _data ) ); + return new audioFileProcessor(static_cast(model)); } diff --git a/plugins/audio_file_processor/audio_file_processor.h b/plugins/audio_file_processor/audio_file_processor.h index 150807686..0df7eeaf1 100644 --- a/plugins/audio_file_processor/audio_file_processor.h +++ b/plugins/audio_file_processor/audio_file_processor.h @@ -111,7 +111,7 @@ private: class AudioFileProcessorWaveView; -class AudioFileProcessorView : public InstrumentView +class AudioFileProcessorView : public InstrumentViewFixedSize { Q_OBJECT public: @@ -211,7 +211,6 @@ public: private: bool checkBound( double _v ) const; - } ; @@ -276,6 +275,7 @@ private: void updateGraph(); void reverse(); + void updateCursor( QMouseEvent * _me = nullptr ); static bool isCloseTo( int _a, int _b ) { diff --git a/plugins/bit_invader/bit_invader.cpp b/plugins/bit_invader/bit_invader.cpp index 86069a13c..caa272fa7 100644 --- a/plugins/bit_invader/bit_invader.cpp +++ b/plugins/bit_invader/bit_invader.cpp @@ -36,13 +36,14 @@ #include "NotePlayHandle.h" #include "Oscillator.h" #include "PixmapButton.h" -#include "templates.h" #include "ToolTip.h" #include "Song.h" #include "interpolation.h" #include "embed.h" +#include "plugin_export.h" + extern "C" { @@ -63,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; } @@ -86,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() ) ); @@ -139,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(); @@ -277,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() ); @@ -289,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; @@ -325,7 +326,7 @@ PluginView * bitInvader::instantiateView( QWidget * _parent ) bitInvaderView::bitInvaderView( Instrument * _instrument, QWidget * _parent ) : - InstrumentView( _instrument, _parent ) + InstrumentViewFixedSize( _instrument, _parent ) { setAutoFillBackground( true ); QPalette pal; @@ -472,6 +473,7 @@ void bitInvaderView::modelChanged() void bitInvaderView::sinWaveClicked() { + m_graph->model()->clearInvisible(); m_graph->model()->setWaveToSine(); Engine::getSong()->setModified(); } @@ -481,6 +483,7 @@ void bitInvaderView::sinWaveClicked() void bitInvaderView::triangleWaveClicked() { + m_graph->model()->clearInvisible(); m_graph->model()->setWaveToTriangle(); Engine::getSong()->setModified(); } @@ -490,6 +493,7 @@ void bitInvaderView::triangleWaveClicked() void bitInvaderView::sawWaveClicked() { + m_graph->model()->clearInvisible(); m_graph->model()->setWaveToSaw(); Engine::getSong()->setModified(); } @@ -499,6 +503,7 @@ void bitInvaderView::sawWaveClicked() void bitInvaderView::sqrWaveClicked() { + m_graph->model()->clearInvisible(); m_graph->model()->setWaveToSquare(); Engine::getSong()->setModified(); } @@ -508,6 +513,7 @@ void bitInvaderView::sqrWaveClicked() void bitInvaderView::noiseWaveClicked() { + m_graph->model()->clearInvisible(); m_graph->model()->setWaveToNoise(); Engine::getSong()->setModified(); } @@ -518,35 +524,12 @@ void bitInvaderView::noiseWaveClicked() void bitInvaderView::usrWaveClicked() { QString fileName = m_graph->model()->setWaveToUser(); - ToolTip::add( m_usrWaveBtn, fileName ); - Engine::getSong()->setModified(); - /* - m_graph->model()->setWaveToNoise(); - Engine::getSong()->setModified(); - // zero sample_shape - for (int i = 0; i < sample_length; i++) + if (!fileName.isEmpty()) { - sample_shape[i] = 0; + ToolTip::add(m_usrWaveBtn, fileName); + m_graph->model()->clearInvisible(); + Engine::getSong()->setModified(); } - - // load user shape - sampleBuffer buffer; - QString af = buffer.openAudioFile(); - if ( af != "" ) - { - buffer.setAudioFile( af ); - - // copy buffer data - sample_length = min( sample_length, static_cast( - buffer.frames() ) ); - for ( int i = 0; i < sample_length; i++ ) - { - sample_shape[i] = (float)*buffer.data()[i]; - } - } - - sampleChanged(); - */ } @@ -582,14 +565,10 @@ extern "C" { // necessary for getting instance out of shared lib -PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *, void * _data ) +PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *m, void * ) { - return( new bitInvader( static_cast( _data ) ) ); + return( new bitInvader( static_cast( m ) ) ); } } - - - - diff --git a/plugins/bit_invader/bit_invader.h b/plugins/bit_invader/bit_invader.h index 1489ab104..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; @@ -108,7 +107,7 @@ private: -class bitInvaderView : public InstrumentView +class bitInvaderView : public InstrumentViewFixedSize { Q_OBJECT public: diff --git a/plugins/carlabase/CMakeLists.txt b/plugins/carlabase/CMakeLists.txt index 48a637c62..0311ca8ee 100644 --- a/plugins/carlabase/CMakeLists.txt +++ b/plugins/carlabase/CMakeLists.txt @@ -1,3 +1,11 @@ +# For MacOS, use "OLD" RPATH install_name behavior +# This can be changed to "NEW" safely if install_apple.sh.in +# is updated to relink libcarlabase.dylib. MacOS 10.8 uses +# cmake 3.9.6, so this can be done at any time. +IF(NOT CMAKE_VERSION VERSION_LESS 3.9) + CMAKE_POLICY(SET CMP0068 OLD) +ENDIF() + if(LMMS_HAVE_CARLA) INCLUDE(BuildPlugin) INCLUDE_DIRECTORIES(${CARLA_INCLUDE_DIRS}) diff --git a/plugins/carlabase/carla.cpp b/plugins/carlabase/carla.cpp index 2cec98220..ba2dd085c 100644 --- a/plugins/carlabase/carla.cpp +++ b/plugins/carlabase/carla.cpp @@ -1,7 +1,7 @@ /* * carla.cpp - Carla for LMMS * - * Copyright (C) 2014 Filipe Coelho + * Copyright (C) 2014-2018 Filipe Coelho * * This file is part of LMMS - https://lmms.io * @@ -24,9 +24,6 @@ #include "carla.h" -#define REAL_BUILD // FIXME this shouldn't be needed -#include "CarlaHost.h" - #include "Engine.h" #include "Song.h" #include "gui_templates.h" @@ -132,14 +129,6 @@ static const char* host_ui_save_file(NativeHostHandle, bool isDir, const char* t // ----------------------------------------------------------------------- -CARLA_EXPORT -const NativePluginDescriptor* carla_get_native_patchbay_plugin(); - -CARLA_EXPORT -const NativePluginDescriptor* carla_get_native_rack_plugin(); - -// ----------------------------------------------------------------------- - CarlaInstrument::CarlaInstrument(InstrumentTrack* const instrumentTrack, const Descriptor* const descriptor, const bool isPatchbay) : Instrument(instrumentTrack, descriptor), kIsPatchbay(isPatchbay), @@ -161,8 +150,9 @@ CarlaInstrument::CarlaInstrument(InstrumentTrack* const instrumentTrack, const D path.cdUp(); resourcesPath = path.absolutePath() + "/share/carla/resources"; #elif defined(CARLA_OS_MAC) - // assume standard install location - resourcesPath = "/Applications/Carla.app/Contents/MacOS/resources"; + // parse prefix from dll filename + QDir path = QFileInfo(dllName).dir(); + resourcesPath = path.absolutePath() + "/resources"; #elif defined(CARLA_OS_WIN32) || defined(CARLA_OS_WIN64) // not yet supported #endif @@ -254,7 +244,7 @@ void CarlaInstrument::handleUiClosed() emit uiClosed(); } -intptr_t CarlaInstrument::handleDispatcher(const NativeHostDispatcherOpcode opcode, const int32_t index, const intptr_t value, void* const ptr, const float opt) +intptr_t CarlaInstrument::handleDispatcher(const NativeHostDispatcherOpcode opcode, const int32_t, const intptr_t, void* const, const float) { intptr_t ret = 0; @@ -267,13 +257,10 @@ intptr_t CarlaInstrument::handleDispatcher(const NativeHostDispatcherOpcode opco qApp->processEvents(); break; default: - break; + break; } return ret; - - // unused for now - (void)index; (void)value; (void)ptr; (void)opt; } // ------------------------------------------------------------------- @@ -337,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; @@ -448,9 +435,12 @@ bool CarlaInstrument::handleMidiEvent(const MidiEvent& event, const MidiTime&, f PluginView* CarlaInstrument::instantiateView(QWidget* parent) { +// Disable plugin focus per https://bugreports.qt.io/browse/QTBUG-30181 +#ifndef CARLA_OS_MAC if (QWidget* const window = parent->window()) fHost.uiParentId = window->winId(); else +#endif fHost.uiParentId = 0; std::free((char*)fHost.uiName); @@ -470,7 +460,7 @@ void CarlaInstrument::sampleRateChanged() // ------------------------------------------------------------------- CarlaInstrumentView::CarlaInstrumentView(CarlaInstrument* const instrument, QWidget* const parent) - : InstrumentView(instrument, parent), + : InstrumentViewFixedSize(instrument, parent), fHandle(instrument->fHandle), fDescriptor(instrument->fDescriptor), fTimerId(fHandle != NULL && fDescriptor->ui_idle != NULL ? startTimer(30) : 0) diff --git a/plugins/carlabase/carla.h b/plugins/carlabase/carla.h index 6431e5300..393912a50 100644 --- a/plugins/carlabase/carla.h +++ b/plugins/carlabase/carla.h @@ -1,7 +1,7 @@ /* * carla.h - Carla for LMMS * - * Copyright (C) 2014 Filipe Coelho + * Copyright (C) 2014-2018 Filipe Coelho * * This file is part of LMMS - https://lmms.io * @@ -26,8 +26,22 @@ #define CARLA_H #include +#include "plugin_export.h" #include "CarlaNative.h" +#define REAL_BUILD // FIXME this shouldn't be needed +#if CARLA_VERSION_HEX >= 0x010911 + #include "CarlaNativePlugin.h" +#else + #include "CarlaBackend.h" + #include "CarlaNative.h" + #include "CarlaUtils.h" + CARLA_EXPORT + const NativePluginDescriptor* carla_get_native_patchbay_plugin(); + + CARLA_EXPORT + const NativePluginDescriptor* carla_get_native_rack_plugin(); +#endif #include "Instrument.h" #include "InstrumentView.h" @@ -44,7 +58,7 @@ public: CarlaInstrument(InstrumentTrack* const instrumentTrack, const Descriptor* const descriptor, const bool isPatchbay); virtual ~CarlaInstrument(); - // CarlaNative functions + // Carla NativeHostDescriptor functions uint32_t handleGetBufferSize() const; double handleGetSampleRate() const; bool handleIsOffline() const; @@ -85,7 +99,7 @@ private: friend class CarlaInstrumentView; }; -class CarlaInstrumentView : public InstrumentView +class CarlaInstrumentView : public InstrumentViewFixedSize { Q_OBJECT diff --git a/plugins/carlapatchbay/carlapatchbay.cpp b/plugins/carlapatchbay/carlapatchbay.cpp index d67ffebb8..ac00630d4 100644 --- a/plugins/carlapatchbay/carlapatchbay.cpp +++ b/plugins/carlapatchbay/carlapatchbay.cpp @@ -1,7 +1,7 @@ /* * carlapatchbay.cpp - Carla for LMMS (Patchbay) * - * Copyright (C) 2014 Filipe Coelho + * Copyright (C) 2014-2018 Filipe Coelho * * This file is part of LMMS - https://lmms.io * @@ -25,6 +25,7 @@ #include "carla.h" #include "embed.h" +#include "InstrumentTrack.h" extern "C" { @@ -36,16 +37,16 @@ Plugin::Descriptor PLUGIN_EXPORT carlapatchbay_plugin_descriptor = QT_TRANSLATE_NOOP( "pluginBrowser", "Carla Patchbay Instrument" ), "falkTX ", - 0x0195, + CARLA_VERSION_HEX, Plugin::Instrument, new PluginPixmapLoader( "logo" ), NULL, NULL } ; -Plugin* PLUGIN_EXPORT lmms_plugin_main(Model*, void* data) +PLUGIN_EXPORT Plugin* lmms_plugin_main(Model* m, void*) { - return new CarlaInstrument(static_cast(data), &carlapatchbay_plugin_descriptor, true); + return new CarlaInstrument(static_cast(m), &carlapatchbay_plugin_descriptor, true); } } diff --git a/plugins/carlarack/carlarack.cpp b/plugins/carlarack/carlarack.cpp index 5225f46b9..c0a39f9c2 100644 --- a/plugins/carlarack/carlarack.cpp +++ b/plugins/carlarack/carlarack.cpp @@ -1,7 +1,7 @@ /* * carlarack.cpp - Carla for LMMS (Rack) * - * Copyright (C) 2014 Filipe Coelho + * Copyright (C) 2014-2018 Filipe Coelho * * This file is part of LMMS - https://lmms.io * @@ -25,6 +25,7 @@ #include "carla.h" #include "embed.h" +#include "InstrumentTrack.h" extern "C" { @@ -36,16 +37,16 @@ Plugin::Descriptor PLUGIN_EXPORT carlarack_plugin_descriptor = QT_TRANSLATE_NOOP( "pluginBrowser", "Carla Rack Instrument" ), "falkTX ", - 0x0195, + CARLA_VERSION_HEX, Plugin::Instrument, new PluginPixmapLoader( "logo" ), NULL, NULL } ; -Plugin* PLUGIN_EXPORT lmms_plugin_main(Model*, void* data) +PLUGIN_EXPORT Plugin* lmms_plugin_main(Model* m, void*) { - return new CarlaInstrument(static_cast(data), &carlarack_plugin_descriptor, false); + return new CarlaInstrument(static_cast(m), &carlarack_plugin_descriptor, false); } } diff --git a/plugins/dynamics_processor/dynamics_processor.cpp b/plugins/dynamics_processor/dynamics_processor.cpp index 12ed1fa88..8c02b827d 100644 --- a/plugins/dynamics_processor/dynamics_processor.cpp +++ b/plugins/dynamics_processor/dynamics_processor.cpp @@ -29,6 +29,7 @@ #include "interpolation.h" #include "embed.h" +#include "plugin_export.h" extern "C" { diff --git a/plugins/kicker/kicker.cpp b/plugins/kicker/kicker.cpp index 0318c92d2..5f36aae93 100644 --- a/plugins/kicker/kicker.cpp +++ b/plugins/kicker/kicker.cpp @@ -36,7 +36,7 @@ #include "KickerOsc.h" #include "embed.h" - +#include "plugin_export.h" extern "C" { @@ -267,7 +267,7 @@ public: kickerInstrumentView::kickerInstrumentView( Instrument * _instrument, QWidget * _parent ) : - InstrumentView( _instrument, _parent ) + InstrumentViewFixedSize( _instrument, _parent ) { const int ROW1 = 14; const int ROW2 = ROW1 + 56; @@ -367,9 +367,9 @@ extern "C" { // necessary for getting instance out of shared lib -PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *, void * _data ) +PLUGIN_EXPORT Plugin * lmms_plugin_main( Model * m, void * ) { - return new kickerInstrument( static_cast( _data ) ); + return new kickerInstrument( static_cast( m ) ); } diff --git a/plugins/kicker/kicker.h b/plugins/kicker/kicker.h index 295887c2f..22b2b854f 100644 --- a/plugins/kicker/kicker.h +++ b/plugins/kicker/kicker.h @@ -94,7 +94,7 @@ private: -class kickerInstrumentView : public InstrumentView +class kickerInstrumentView : public InstrumentViewFixedSize { Q_OBJECT public: diff --git a/plugins/ladspa_browser/ladspa_browser.cpp b/plugins/ladspa_browser/ladspa_browser.cpp index 0e8275c4d..d265bc0e3 100644 --- a/plugins/ladspa_browser/ladspa_browser.cpp +++ b/plugins/ladspa_browser/ladspa_browser.cpp @@ -39,7 +39,7 @@ #include "TabButton.h" #include "embed.h" - +#include "plugin_export.h" extern "C" diff --git a/plugins/lb302/lb302.cpp b/plugins/lb302/lb302.cpp index 66b77ac35..ad3d33b0a 100644 --- a/plugins/lb302/lb302.cpp +++ b/plugins/lb302/lb302.cpp @@ -41,12 +41,11 @@ #include "NotePlayHandle.h" #include "Oscillator.h" #include "PixmapButton.h" -#include "templates.h" #include "ToolTip.h" #include "BandLimitedWave.h" #include "embed.h" - +#include "plugin_export.h" // Envelope Recalculation period #define ENVINC 64 @@ -434,11 +433,7 @@ QString lb302Synth::nodeName() const // OBSOLETE. Break apart once we get Q_OBJECT to work. >:[ void lb302Synth::recalcFilter() { -#if QT_VERSION >= 0x050000 vcf.load()->recalc(); -#else - vcf->recalc(); -#endif // THIS IS OLD 3pole/24dB code, I may reintegrate it. Don't need it // right now. Should be toggled by LB_24_RES_TRICK at the moment. @@ -464,11 +459,7 @@ int lb302Synth::process(sampleFrame *outbuf, const int size) float samp; // Hold on to the current VCF, and use it throughout this period -#if QT_VERSION >= 0x050000 lb302Filter *filter = vcf.loadAcquire(); -#else - lb302Filter *filter = vcf; -#endif if( release_frame == 0 || ! m_playingNote ) { @@ -692,11 +683,7 @@ void lb302Synth::initNote( lb302Note *n) if(n->dead ==0){ // Swap next two blocks?? -#if QT_VERSION >= 0x050000 vcf.load()->playNote(); -#else - vcf->playNote(); -#endif // Ensure envelope is recalculated vcf_envpos = ENVINC; @@ -816,7 +803,7 @@ PluginView * lb302Synth::instantiateView( QWidget * _parent ) lb302SynthView::lb302SynthView( Instrument * _instrument, QWidget * _parent ) : - InstrumentView( _instrument, _parent ) + InstrumentViewFixedSize( _instrument, _parent ) { // GUI m_vcfCutKnob = new Knob( knobBright_26, this ); @@ -1041,11 +1028,11 @@ extern "C" { // necessary for getting instance out of shared lib -PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *, void * _data ) +PLUGIN_EXPORT Plugin * lmms_plugin_main( Model * m, void * ) { return( new lb302Synth( - static_cast( _data ) ) ); + static_cast( m ) ) ); } diff --git a/plugins/lb302/lb302.h b/plugins/lb302/lb302.h index 3ca22c78b..557d958d4 100644 --- a/plugins/lb302/lb302.h +++ b/plugins/lb302/lb302.h @@ -256,7 +256,7 @@ private: } ; -class lb302SynthView : public InstrumentView +class lb302SynthView : public InstrumentViewFixedSize { Q_OBJECT public: diff --git a/plugins/monstro/Monstro.cpp b/plugins/monstro/Monstro.cpp index 82f365ec1..efb351fc8 100644 --- a/plugins/monstro/Monstro.cpp +++ b/plugins/monstro/Monstro.cpp @@ -28,7 +28,6 @@ #include "Monstro.h" #include "Engine.h" #include "InstrumentTrack.h" -#include "templates.h" #include "gui_templates.h" #include "ToolTip.h" #include "Song.h" @@ -37,6 +36,7 @@ #include "embed.h" +#include "plugin_export.h" extern "C" { @@ -99,6 +99,11 @@ MonstroSynth::MonstroSynth( MonstroInstrument * _i, NotePlayHandle * _nph ) : m_counter2r = 0; m_counter3l = 0; m_counter3r = 0; + + m_lfo[0].resize( m_parent->m_fpp ); + m_lfo[1].resize( m_parent->m_fpp ); + m_env[0].resize( m_parent->m_fpp ); + m_env[1].resize( m_parent->m_fpp ); } @@ -113,31 +118,31 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) // macros for modulating with env/lfos #define modulatefreq( car, mod ) \ modtmp = 0.0f; \ - if( mod##_e1 != 0.0f ) modtmp += env[0][f] * mod##_e1; \ - if( mod##_e2 != 0.0f ) modtmp += env[1][f] * mod##_e2; \ - if( mod##_l1 != 0.0f ) modtmp += lfo[0][f] * mod##_l1; \ - if( mod##_l2 != 0.0f ) modtmp += lfo[1][f] * mod##_l2; \ + if( mod##_e1 != 0.0f ) modtmp += m_env[0][f] * mod##_e1; \ + if( mod##_e2 != 0.0f ) modtmp += m_env[1][f] * mod##_e2; \ + if( mod##_l1 != 0.0f ) modtmp += m_lfo[0][f] * mod##_l1; \ + if( mod##_l2 != 0.0f ) modtmp += m_lfo[1][f] * mod##_l2; \ car = qBound( MIN_FREQ, car * powf( 2.0f, modtmp ), MAX_FREQ ); #define modulateabs( car, mod ) \ - if( mod##_e1 != 0.0f ) car += env[0][f] * mod##_e1; \ - if( mod##_e2 != 0.0f ) car += env[1][f] * mod##_e2; \ - if( mod##_l1 != 0.0f ) car += lfo[0][f] * mod##_l1; \ - if( mod##_l2 != 0.0f ) car += lfo[1][f] * mod##_l2; + if( mod##_e1 != 0.0f ) car += m_env[0][f] * mod##_e1; \ + if( mod##_e2 != 0.0f ) car += m_env[1][f] * mod##_e2; \ + if( mod##_l1 != 0.0f ) car += m_lfo[0][f] * mod##_l1; \ + if( mod##_l2 != 0.0f ) car += m_lfo[1][f] * mod##_l2; #define modulatephs( car, mod ) \ - if( mod##_e1 != 0.0f ) car += env[0][f] * mod##_e1; \ - if( mod##_e2 != 0.0f ) car += env[1][f] * mod##_e2; \ - if( mod##_l1 != 0.0f ) car += lfo[0][f] * mod##_l1; \ - if( mod##_l2 != 0.0f ) car += lfo[1][f] * mod##_l2; + if( mod##_e1 != 0.0f ) car += m_env[0][f] * mod##_e1; \ + if( mod##_e2 != 0.0f ) car += m_env[1][f] * mod##_e2; \ + if( mod##_l1 != 0.0f ) car += m_lfo[0][f] * mod##_l1; \ + if( mod##_l2 != 0.0f ) car += m_lfo[1][f] * mod##_l2; #define modulatevol( car, mod ) \ - if( mod##_e1 > 0.0f ) car *= ( 1.0f - mod##_e1 + mod##_e1 * env[0][f] ); \ - if( mod##_e1 < 0.0f ) car *= ( 1.0f + mod##_e1 * env[0][f] ); \ - if( mod##_e2 > 0.0f ) car *= ( 1.0f - mod##_e2 + mod##_e2 * env[1][f] ); \ - if( mod##_e2 < 0.0f ) car *= ( 1.0f + mod##_e2 * env[1][f] ); \ - if( mod##_l1 != 0.0f ) car *= ( 1.0f + mod##_l1 * lfo[0][f] ); \ - if( mod##_l2 != 0.0f ) car *= ( 1.0f + mod##_l2 * lfo[1][f] ); \ + if( mod##_e1 > 0.0f ) car *= ( 1.0f - mod##_e1 + mod##_e1 * m_env[0][f] ); \ + if( mod##_e1 < 0.0f ) car *= ( 1.0f + mod##_e1 * m_env[0][f] ); \ + if( mod##_e2 > 0.0f ) car *= ( 1.0f - mod##_e2 + mod##_e2 * m_env[1][f] ); \ + if( mod##_e2 < 0.0f ) car *= ( 1.0f + mod##_e2 * m_env[1][f] ); \ + if( mod##_l1 != 0.0f ) car *= ( 1.0f + mod##_l1 * m_lfo[0][f] ); \ + if( mod##_l2 != 0.0f ) car *= ( 1.0f + mod##_l2 * m_lfo[1][f] ); \ car = qBound( -MODCLIP, car, MODCLIP ); @@ -323,7 +328,7 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) float o1l_f; float o1r_f; float o1l_p = m_osc1l_phase + o1lpo; // we add phase offset here so we don't have to do it every frame - float o1r_p = m_osc1r_phase + o1rpo; // then substract it again after loop... + float o1r_p = m_osc1r_phase + o1rpo; // then subtract it again after loop... float o1_pw; // osc2 vars @@ -339,12 +344,8 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) float o3r_p = m_osc3r_phase + o3rpo; float sub; - // modulators - float lfo[2][ m_parent->m_fpp ]; - float env[2][ m_parent->m_fpp ]; - // render modulators: envelopes, lfos - updateModulators( &env[0][0], &env[1][0], &lfo[0][0], &lfo[1][0], _frames ); + updateModulators( m_env[0].data(), m_env[1].data(), m_lfo[0].data(), m_lfo[1].data(), _frames ); // begin for loop for( f_cnt_t f = 0; f < _frames; ++f ) @@ -1446,7 +1447,7 @@ void MonstroInstrument::updateSlope2() MonstroView::MonstroView( Instrument * _instrument, QWidget * _parent ) : - InstrumentView( _instrument, _parent ) + InstrumentViewFixedSize( _instrument, _parent ) { m_operatorsView = setupOperatorsView( this ); setWidgetBackground( m_operatorsView, "artwork_op" ); @@ -1826,9 +1827,9 @@ extern "C" { // necessary for getting instance out of shared lib -PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *, void * _data ) +PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *m, void * ) { - return new MonstroInstrument( static_cast( _data ) ); + return new MonstroInstrument( static_cast( m ) ); } diff --git a/plugins/monstro/Monstro.h b/plugins/monstro/Monstro.h index 2cf05f300..fc0cc13b0 100644 --- a/plugins/monstro/Monstro.h +++ b/plugins/monstro/Monstro.h @@ -26,6 +26,7 @@ #ifndef MONSTRO_H #define MONSTRO_H +#include #include "Instrument.h" #include "InstrumentView.h" @@ -299,6 +300,9 @@ private: int m_counter2r; int m_counter3l; int m_counter3r; + + std::vector m_lfo[2]; + std::vector m_env[2]; }; class MonstroInstrument : public Instrument @@ -565,7 +569,7 @@ private: }; -class MonstroView : public InstrumentView +class MonstroView : public InstrumentViewFixedSize { Q_OBJECT public: diff --git a/plugins/monstro/exp.png b/plugins/monstro/exp.png index 9fe634881..acb7a55cb 100644 Binary files a/plugins/monstro/exp.png and b/plugins/monstro/exp.png differ diff --git a/plugins/monstro/moog.png b/plugins/monstro/moog.png index 6d9005966..f206bd0da 100644 Binary files a/plugins/monstro/moog.png and b/plugins/monstro/moog.png differ diff --git a/plugins/monstro/noise.png b/plugins/monstro/noise.png index 6d3853f60..dbdad6832 100644 Binary files a/plugins/monstro/noise.png and b/plugins/monstro/noise.png differ diff --git a/plugins/monstro/ramp.png b/plugins/monstro/ramp.png index dbd423efd..5061f6ed7 100644 Binary files a/plugins/monstro/ramp.png and b/plugins/monstro/ramp.png differ diff --git a/plugins/monstro/saw.png b/plugins/monstro/saw.png index 56c077f2c..3122b082f 100644 Binary files a/plugins/monstro/saw.png and b/plugins/monstro/saw.png differ diff --git a/plugins/monstro/sin.png b/plugins/monstro/sin.png index acabd5a17..3ac3c9afa 100644 Binary files a/plugins/monstro/sin.png and b/plugins/monstro/sin.png differ diff --git a/plugins/monstro/sinabs.png b/plugins/monstro/sinabs.png index 2216224e6..e28d1ec21 100644 Binary files a/plugins/monstro/sinabs.png and b/plugins/monstro/sinabs.png differ diff --git a/plugins/monstro/sqr.png b/plugins/monstro/sqr.png index 83d5e4869..d5d3c211c 100644 Binary files a/plugins/monstro/sqr.png and b/plugins/monstro/sqr.png differ diff --git a/plugins/monstro/sqrsoft.png b/plugins/monstro/sqrsoft.png index 2e5626d20..037fcab12 100644 Binary files a/plugins/monstro/sqrsoft.png and b/plugins/monstro/sqrsoft.png differ diff --git a/plugins/monstro/tri.png b/plugins/monstro/tri.png index 9e1ab8108..01119f894 100644 Binary files a/plugins/monstro/tri.png and b/plugins/monstro/tri.png differ diff --git a/plugins/nes/Nes.cpp b/plugins/nes/Nes.cpp index 70251c6cc..d4bcc6881 100644 --- a/plugins/nes/Nes.cpp +++ b/plugins/nes/Nes.cpp @@ -27,7 +27,6 @@ #include "Nes.h" #include "Engine.h" #include "InstrumentTrack.h" -#include "templates.h" #include "ToolTip.h" #include "Song.h" #include "lmms_math.h" @@ -36,6 +35,7 @@ #include "Oscillator.h" #include "embed.h" +#include "plugin_export.h" extern "C" { @@ -519,7 +519,7 @@ NesInstrument::NesInstrument( InstrumentTrack * instrumentTrack ) : m_ch3Volume( 15.f, 0.f, 15.f, 1.f, this, tr( "Channel 3 volume" ) ), //channel 4 - m_ch4Enabled( true, this ), + m_ch4Enabled( false, this ), m_ch4Volume( 15.f, 0.f, 15.f, 1.f, this, tr( "Channel 4 volume" ) ), m_ch4EnvEnabled( false, this ), @@ -731,7 +731,7 @@ QPixmap * NesInstrumentView::s_artwork = NULL; NesInstrumentView::NesInstrumentView( Instrument * instrument, QWidget * parent ) : - InstrumentView( instrument, parent ) + InstrumentViewFixedSize( instrument, parent ) { setAutoFillBackground( true ); QPalette pal; @@ -917,9 +917,9 @@ extern "C" { // necessary for getting instance out of shared lib -PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *, void * _data ) +PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *m, void * _data ) { - return( new NesInstrument( static_cast( _data ) ) ); + return( new NesInstrument( static_cast( m ) ) ); } diff --git a/plugins/nes/Nes.h b/plugins/nes/Nes.h index 20f703739..bbf326d32 100644 --- a/plugins/nes/Nes.h +++ b/plugins/nes/Nes.h @@ -294,7 +294,7 @@ private: }; -class NesInstrumentView : public InstrumentView +class NesInstrumentView : public InstrumentViewFixedSize { Q_OBJECT public: diff --git a/plugins/organic/organic.cpp b/plugins/organic/organic.cpp index 2339587b5..6eb933afa 100644 --- a/plugins/organic/organic.cpp +++ b/plugins/organic/organic.cpp @@ -37,12 +37,11 @@ #include "NotePlayHandle.h" #include "Oscillator.h" #include "PixmapButton.h" -#include "templates.h" #include "ToolTip.h" #include "embed.h" - +#include "plugin_export.h" extern "C" @@ -233,8 +232,8 @@ void organicInstrument::playNote( NotePlayHandle * _n, if( _n->totalFramesPlayed() == 0 || _n->m_pluginData == NULL ) { - Oscillator * oscs_l[m_numOscillators]; - Oscillator * oscs_r[m_numOscillators]; + Oscillator * oscs_l[NUM_OSCILLATORS]; + Oscillator * oscs_r[NUM_OSCILLATORS]; _n->m_pluginData = new oscPtr; @@ -307,7 +306,7 @@ void organicInstrument::playNote( NotePlayHandle * _n, // fxKnob is [0;1] float t = m_fx1Model.value(); - for (int i=0 ; i < frames ; i++) + for (int i=0 ; i < frames + offset ; i++) { _working_buffer[i][0] = waveshape( _working_buffer[i][0], t ) * m_volModel.value() / 100.0f; @@ -418,7 +417,7 @@ public: organicInstrumentView::organicInstrumentView( Instrument * _instrument, QWidget * _parent ) : - InstrumentView( _instrument, _parent ), + InstrumentViewFixedSize( _instrument, _parent ), m_oscKnobs( NULL ) { organicInstrument * oi = castModel(); @@ -636,9 +635,9 @@ extern "C" { // necessary for getting instance out of shared lib -PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *, void * _data ) +PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *m, void * ) { - return( new organicInstrument( static_cast( _data ) ) ); + return( new organicInstrument( static_cast( m ) ) ); } diff --git a/plugins/organic/organic.h b/plugins/organic/organic.h index 86b25ea77..c0bc29f16 100644 --- a/plugins/organic/organic.h +++ b/plugins/organic/organic.h @@ -173,7 +173,7 @@ private slots: } ; -class organicInstrumentView : public InstrumentView +class organicInstrumentView : public InstrumentViewFixedSize { Q_OBJECT public: diff --git a/plugins/patman/patman.cpp b/plugins/patman/patman.cpp index bf24c6d32..8a0c71340 100644 --- a/plugins/patman/patman.cpp +++ b/plugins/patman/patman.cpp @@ -44,7 +44,7 @@ #include "embed.h" - +#include "plugin_export.h" extern "C" @@ -66,9 +66,9 @@ Plugin::Descriptor PLUGIN_EXPORT patman_plugin_descriptor = // necessary for getting instance out of shared lib -PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *, void * _data ) +PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *m, void * ) { - return new patmanInstrument( static_cast( _data ) ); + return new patmanInstrument( static_cast( m ) ); } } @@ -78,7 +78,6 @@ PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *, void * _data ) patmanInstrument::patmanInstrument( InstrumentTrack * _instrument_track ) : Instrument( _instrument_track, &patman_plugin_descriptor ), - m_patchFile( QString::null ), m_loopedModel( true, this ), m_tunedModel( true, this ) { @@ -182,7 +181,7 @@ void patmanInstrument::setFile( const QString & _patch_file, bool _rename ) { if( _patch_file.size() <= 0 ) { - m_patchFile = QString::null; + m_patchFile = QString(); return; } @@ -444,7 +443,7 @@ PluginView * patmanInstrument::instantiateView( QWidget * _parent ) PatmanView::PatmanView( Instrument * _instrument, QWidget * _parent ) : - InstrumentView( _instrument, _parent ), + InstrumentViewFixedSize( _instrument, _parent ), m_pi( NULL ) { setAutoFillBackground( true ); diff --git a/plugins/patman/patman.h b/plugins/patman/patman.h index a3b5a39b8..8d5689b73 100644 --- a/plugins/patman/patman.h +++ b/plugins/patman/patman.h @@ -116,7 +116,7 @@ signals: -class PatmanView : public InstrumentView +class PatmanView : public InstrumentViewFixedSize { Q_OBJECT public: diff --git a/plugins/peak_controller_effect/peak_controller_effect.cpp b/plugins/peak_controller_effect/peak_controller_effect.cpp index 2b39352ff..9d1e6ccf4 100644 --- a/plugins/peak_controller_effect/peak_controller_effect.cpp +++ b/plugins/peak_controller_effect/peak_controller_effect.cpp @@ -32,6 +32,7 @@ #include "lmms_math.h" #include "embed.h" +#include "plugin_export.h" extern "C" { @@ -64,7 +65,7 @@ PeakControllerEffect::PeakControllerEffect( Effect( &peakcontrollereffect_plugin_descriptor, _parent, _key ), m_effectId( rand() ), m_peakControls( this ), - m_lastSample( m_peakControls.m_baseModel.value() ), //sets the value to the Peak Controller's Base value (rather than 0 like in previous versions) + m_lastSample( 0 ), m_autoController( NULL ) { m_autoController = new PeakController( Engine::getSong(), this ); 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.cpp b/plugins/peak_controller_effect/peak_controller_effect_controls.cpp index 08d207a10..ff87d0d99 100644 --- a/plugins/peak_controller_effect/peak_controller_effect_controls.cpp +++ b/plugins/peak_controller_effect/peak_controller_effect_controls.cpp @@ -53,6 +53,7 @@ PeakControllerEffectControls( PeakControllerEffect * _eff ) : void PeakControllerEffectControls::loadSettings( const QDomElement & _this ) { m_baseModel.loadSettings( _this, "base" ); + m_effect->m_lastSample = m_baseModel.value(); //Set initial Peak Controller output to Base m_amountModel.loadSettings( _this, "amount" ); m_muteModel.loadSettings( _this, "mute" ); diff --git a/plugins/peak_controller_effect/peak_controller_effect_controls.h b/plugins/peak_controller_effect/peak_controller_effect_controls.h index 784df4d8d..fe90eddca 100644 --- a/plugins/peak_controller_effect/peak_controller_effect_controls.h +++ b/plugins/peak_controller_effect/peak_controller_effect_controls.h @@ -41,18 +41,18 @@ public: { } - virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent ); - virtual void loadSettings( const QDomElement & _this ); - inline virtual QString nodeName() const + void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override; + void loadSettings( const QDomElement & _this ) override; + inline QString nodeName() const override { return "peakcontrollereffectcontrols"; } - virtual int controlCount() + int controlCount() override { return 1; } - virtual EffectControlDialog * createView() + EffectControlDialog * createView() override { return new PeakControllerEffectControlDialog( this ); } diff --git a/plugins/sf2_player/fluidsynthshims.h b/plugins/sf2_player/fluidsynthshims.h new file mode 100644 index 000000000..4302256ba --- /dev/null +++ b/plugins/sf2_player/fluidsynthshims.h @@ -0,0 +1,88 @@ +/* + * fluidsynthshims.h - a shim header for FluidSynth 2.0 API changes + * + * Copyright (c) 2018 Hyunjin Song + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + + +#ifndef FLUIDSYNTHSHIMS_H +#define FLUIDSYNTHSHIMS_H + +#include + +#if FLUIDSYNTH_VERSION_MAJOR < 2 + +inline const char* fluid_preset_get_name(fluid_preset_t* preset) +{ + return preset->get_name(preset); +} + +inline int fluid_preset_get_banknum(fluid_preset_t* preset) +{ + return preset->get_banknum(preset); +} + +inline int fluid_preset_get_num(fluid_preset_t* preset) +{ + return preset->get_num(preset); +} + +inline fluid_sfont_t* fluid_preset_get_sfont(fluid_preset_t* preset) +{ + return preset->sfont; +} + +inline char* fluid_sfont_get_name(fluid_sfont_t* sfont) +{ + return sfont->get_name(sfont); +} + +inline void fluid_sfont_iteration_start(fluid_sfont_t* sfont) +{ + sfont->iteration_start(sfont); +} + +// Due to the API change, we can't simply shim the 'fluid_sfont_iteration_next' function +inline fluid_preset_t* fluid_sfont_iteration_next_wrapper(fluid_sfont_t* sfont, fluid_preset_t* preset) +{ + return sfont->iteration_next(sfont, preset) ? preset : nullptr; +} + +#else // FLUIDSYNTH_VERSION_MAJOR < 2 + +#define FLUID_REVERB_DEFAULT_ROOMSIZE 0.2f +#define FLUID_REVERB_DEFAULT_DAMP 0.0f +#define FLUID_REVERB_DEFAULT_WIDTH 0.5f +#define FLUID_REVERB_DEFAULT_LEVEL 0.9f + +#define FLUID_CHORUS_DEFAULT_N 3 +#define FLUID_CHORUS_DEFAULT_LEVEL 2.0f +#define FLUID_CHORUS_DEFAULT_SPEED 0.3f +#define FLUID_CHORUS_DEFAULT_DEPTH 8.0f + +inline fluid_preset_t* fluid_sfont_iteration_next_wrapper(fluid_sfont_t* sfont, fluid_preset_t*) +{ + return fluid_sfont_iteration_next(sfont); +} + +#endif // FLUIDSYNTH_VERSION_MAJOR < 2 + +#endif // FLUIDSYNTHSHIMS_H diff --git a/plugins/sf2_player/patches_dialog.cpp b/plugins/sf2_player/patches_dialog.cpp index 6ae791c15..fe49ab1b3 100644 --- a/plugins/sf2_player/patches_dialog.cpp +++ b/plugins/sf2_player/patches_dialog.cpp @@ -75,11 +75,7 @@ patchesDialog::patchesDialog( QWidget *pParent, Qt::WindowFlags wflags ) // pHeader->setResizeMode(QHeaderView::Custom); pHeader->setDefaultAlignment(Qt::AlignLeft); // pHeader->setDefaultSectionSize(200); -#if QT_VERSION >= 0x050000 pHeader->setSectionsMovable(false); -#else - pHeader->setMovable(false); -#endif pHeader->setStretchLastSection(true); m_progListView->resizeColumnToContents(0); // Prog. @@ -143,7 +139,6 @@ void patchesDialog::setup ( fluid_synth_t * pSynth, int iChan, m_iChan = iChan; - fluid_preset_t preset; QTreeWidgetItem *pBankItem = NULL; // For all soundfonts (in reversed stack order) fill the available banks... int cSoundFonts = ::fluid_synth_sfcount(m_pSynth); @@ -151,11 +146,17 @@ void patchesDialog::setup ( fluid_synth_t * pSynth, int iChan, fluid_sfont_t *pSoundFont = ::fluid_synth_get_sfont(m_pSynth, i); if (pSoundFont) { #ifdef CONFIG_FLUID_BANK_OFFSET - int iBankOffset = ::fluid_synth_get_bank_offset(m_pSynth, pSoundFont->id); + int iBankOffset = ::fluid_synth_get_bank_offset(m_pSynth, fluid_sfont_get_id(pSoundFont)); #endif - pSoundFont->iteration_start(pSoundFont); - while (pSoundFont->iteration_next(pSoundFont, &preset)) { - int iBank = preset.get_banknum(&preset); + fluid_sfont_iteration_start(pSoundFont); +#if FLUIDSYNTH_VERSION_MAJOR < 2 + fluid_preset_t preset; + fluid_preset_t *pCurPreset = &preset; +#else + fluid_preset_t *pCurPreset; +#endif + while ((pCurPreset = fluid_sfont_iteration_next_wrapper(pSoundFont, pCurPreset))) { + int iBank = fluid_preset_get_banknum(pCurPreset); #ifdef CONFIG_FLUID_BANK_OFFSET iBank += iBankOffset; #endif @@ -173,9 +174,9 @@ void patchesDialog::setup ( fluid_synth_t * pSynth, int iChan, m_iBank = 0; fluid_preset_t *pPreset = ::fluid_synth_get_channel_preset(m_pSynth, m_iChan); if (pPreset) { - m_iBank = pPreset->get_banknum(pPreset); + m_iBank = fluid_preset_get_banknum(pPreset); #ifdef CONFIG_FLUID_BANK_OFFSET - m_iBank += ::fluid_synth_get_bank_offset(m_pSynth, (pPreset->sfont)->id); + m_iBank += ::fluid_synth_get_bank_offset(m_pSynth, fluid_sfont_get_id(fluid_preset_get_sfont(sfont))); #endif } @@ -186,7 +187,7 @@ void patchesDialog::setup ( fluid_synth_t * pSynth, int iChan, // Set the selected program. if (pPreset) - m_iProg = pPreset->get_num(pPreset); + m_iProg = fluid_preset_get_num(pPreset); QTreeWidgetItem *pProgItem = findProgItem(m_iProg); m_progListView->setCurrentItem(pProgItem); m_progListView->scrollToItem(pProgItem); @@ -312,7 +313,6 @@ void patchesDialog::bankChanged (void) // Clear up the program listview. m_progListView->setSortingEnabled(false); m_progListView->clear(); - fluid_preset_t preset; QTreeWidgetItem *pProgItem = NULL; // For all soundfonts (in reversed stack order) fill the available programs... int cSoundFonts = ::fluid_synth_sfcount(m_pSynth); @@ -320,23 +320,29 @@ void patchesDialog::bankChanged (void) fluid_sfont_t *pSoundFont = ::fluid_synth_get_sfont(m_pSynth, i); if (pSoundFont) { #ifdef CONFIG_FLUID_BANK_OFFSET - int iBankOffset = ::fluid_synth_get_bank_offset(m_pSynth, pSoundFont->id); + int iBankOffset = ::fluid_synth_get_bank_offset(m_pSynth, fluid_sfont_get_id(pSoundFont)); #endif - pSoundFont->iteration_start(pSoundFont); - while (pSoundFont->iteration_next(pSoundFont, &preset)) { - int iBank = preset.get_banknum(&preset); + fluid_sfont_iteration_start(pSoundFont); +#if FLUIDSYNTH_VERSION_MAJOR < 2 + fluid_preset_t preset; + fluid_preset_t *pCurPreset = &preset; +#else + fluid_preset_t *pCurPreset; +#endif + while ((pCurPreset = fluid_sfont_iteration_next_wrapper(pSoundFont, pCurPreset))) { + int iBank = fluid_preset_get_banknum(pCurPreset); #ifdef CONFIG_FLUID_BANK_OFFSET iBank += iBankOffset; #endif - int iProg = preset.get_num(&preset); + int iProg = fluid_preset_get_num(pCurPreset); if (iBank == iBankSelected && !findProgItem(iProg)) { pProgItem = new patchItem(m_progListView, pProgItem); if (pProgItem) { pProgItem->setText(0, QString::number(iProg)); - pProgItem->setText(1, preset.get_name(&preset)); - //pProgItem->setText(2, QString::number(pSoundFont->id)); + pProgItem->setText(1, fluid_preset_get_name(pCurPreset)); + //pProgItem->setText(2, QString::number(fluid_sfont_get_id(pSoundFont))); //pProgItem->setText(3, QFileInfo( - // pSoundFont->get_name(pSoundFont)).baseName()); + // fluid_sfont_get_name(pSoundFont).baseName()); } } } diff --git a/plugins/sf2_player/patches_dialog.h b/plugins/sf2_player/patches_dialog.h index f4523ff90..a2c88a79d 100644 --- a/plugins/sf2_player/patches_dialog.h +++ b/plugins/sf2_player/patches_dialog.h @@ -29,7 +29,7 @@ #include "ui_patches_dialog.h" #include "LcdSpinBox.h" -#include +#include "fluidsynthshims.h" #include #include diff --git a/plugins/sf2_player/sf2_player.cpp b/plugins/sf2_player/sf2_player.cpp index 93867983d..99af22781 100644 --- a/plugins/sf2_player/sf2_player.cpp +++ b/plugins/sf2_player/sf2_player.cpp @@ -46,7 +46,7 @@ #include "LcdSpinBox.h" #include "embed.h" - +#include "plugin_export.h" extern "C" { @@ -128,7 +128,30 @@ sf2Instrument::sf2Instrument( InstrumentTrack * _instrument_track ) : // everytime we load a new soundfont. m_synth = new_fluid_synth( m_settings ); - loadFile( ConfigManager::inst()->defaultSoundfont() ); +#if FLUIDSYNTH_VERSION_MAJOR >= 2 + // Get the default values from the setting + double settingVal; + + fluid_settings_getnum_default(m_settings, "synth.reverb.room-size", &settingVal); + m_reverbRoomSize.setInitValue(settingVal); + fluid_settings_getnum_default(m_settings, "synth.reverb.damping", &settingVal); + m_reverbDamping.setInitValue(settingVal); + fluid_settings_getnum_default(m_settings, "synth.reverb.width", &settingVal); + m_reverbWidth.setInitValue(settingVal); + fluid_settings_getnum_default(m_settings, "synth.reverb.level", &settingVal); + m_reverbLevel.setInitValue(settingVal); + + fluid_settings_getnum_default(m_settings, "synth.chorus.nr", &settingVal); + m_chorusNum.setInitValue(settingVal); + fluid_settings_getnum_default(m_settings, "synth.chorus.level", &settingVal); + m_chorusLevel.setInitValue(settingVal); + fluid_settings_getnum_default(m_settings, "synth.chorus.speed", &settingVal); + m_chorusSpeed.setInitValue(settingVal); + fluid_settings_getnum_default(m_settings, "synth.chorus.depth", &settingVal); + m_chorusDepth.setInitValue(settingVal); +#endif + + loadFile( ConfigManager::inst()->sf2File() ); updateSampleRate(); updateReverbOn(); @@ -244,6 +267,43 @@ void sf2Instrument::loadFile( const QString & _file ) // soundfont for the first time fails updateSampleRate(); } + + // setting the first bank and patch number that is found + auto sSoundCount = ::fluid_synth_sfcount( m_synth ); + for ( int i = 0; i < sSoundCount; ++i ) { + int iBank = 0; + int iProg = 0; + fluid_sfont_t *pSoundFont = ::fluid_synth_get_sfont( m_synth, i ); + + if ( pSoundFont ) { +#ifdef CONFIG_FLUID_BANK_OFFSET + int iBankOff = ::fluid_synth_get_bank_offset( m_synth, fluid_sfont_get_id( pSoundFont ) ); +#endif + + fluid_sfont_iteration_start( pSoundFont ); +#if FLUIDSYNTH_VERSION_MAJOR < 2 + fluid_preset_t preset; + fluid_preset_t *pCurPreset = &preset; +#else + fluid_preset_t *pCurPreset; +#endif + + if ( ( pCurPreset = fluid_sfont_iteration_next_wrapper( pSoundFont, pCurPreset ) ) ) { + iBank = fluid_preset_get_banknum( pCurPreset ); + iProg = fluid_preset_get_num( pCurPreset ); + +#ifdef CONFIG_FLUID_BANK_OFFSET + iBank += iBankOff; +#endif + + ::fluid_synth_bank_select( m_synth, 1, iBank ); + ::fluid_synth_program_change( m_synth, 1, iProg ); + m_bankNum.setValue( iBank ); + m_patchNum.setValue ( iProg ); + break; + } + } + } } @@ -393,7 +453,6 @@ QString sf2Instrument::getCurrentPatchName() int iBankSelected = m_bankNum.value(); int iProgSelected = m_patchNum.value(); - fluid_preset_t preset; // For all soundfonts (in reversed stack order) fill the available programs... int cSoundFonts = ::fluid_synth_sfcount( m_synth ); for( int i = 0; i < cSoundFonts; i++ ) @@ -404,21 +463,26 @@ QString sf2Instrument::getCurrentPatchName() #ifdef CONFIG_FLUID_BANK_OFFSET int iBankOffset = fluid_synth_get_bank_offset( - m_synth, pSoundFont->id ); + m_synth, fluid_sfont_get_id(pSoundFont) ); #endif - pSoundFont->iteration_start( pSoundFont ); - while( pSoundFont->iteration_next( pSoundFont, - &preset ) ) + fluid_sfont_iteration_start( pSoundFont ); +#if FLUIDSYNTH_VERSION_MAJOR < 2 + fluid_preset_t preset; + fluid_preset_t *pCurPreset = &preset; +#else + fluid_preset_t *pCurPreset; +#endif + while ((pCurPreset = fluid_sfont_iteration_next_wrapper(pSoundFont, pCurPreset))) { - int iBank = preset.get_banknum( &preset ); + int iBank = fluid_preset_get_banknum( pCurPreset ); #ifdef CONFIG_FLUID_BANK_OFFSET iBank += iBankOffset; #endif - int iProg = preset.get_num( &preset ); + int iProg = fluid_preset_get_num( pCurPreset ); if( iBank == iBankSelected && iProg == iProgSelected ) { - return preset.get_name( &preset ); + return fluid_preset_get_name( pCurPreset ); } } } @@ -651,7 +715,6 @@ void sf2Instrument::noteOff( SF2PluginData * n ) fluid_synth_noteoff( m_synth, m_channel, n->midiNote ); m_synthMutex.unlock(); } - } @@ -667,7 +730,6 @@ void sf2Instrument::play( sampleFrame * _working_buffer ) m_synthMutex.lock(); fluid_synth_pitch_bend( m_synth, m_channel, m_lastMidiPitch ); m_synthMutex.unlock(); - } const int currentMidiPitchRange = instrumentTrack()->midiPitchRange(); @@ -832,7 +894,7 @@ public: sf2InstrumentView::sf2InstrumentView( Instrument * _instrument, QWidget * _parent ) : - InstrumentView( _instrument, _parent ) + InstrumentViewFixedSize( _instrument, _parent ) { // QVBoxLayout * vl = new QVBoxLayout( this ); // QHBoxLayout * hl = new QHBoxLayout(); @@ -979,7 +1041,6 @@ sf2InstrumentView::sf2InstrumentView( Instrument * _instrument, QWidget * _paren setPalette( pal ); updateFilename(); - } @@ -1018,7 +1079,6 @@ void sf2InstrumentView::modelChanged() connect( k, SIGNAL( fileLoading() ), this, SLOT( invalidateFile() ) ); updateFilename(); - } @@ -1123,13 +1183,10 @@ extern "C" { // necessary for getting instance out of shared lib -Plugin * PLUGIN_EXPORT lmms_plugin_main( Model *, void * _data ) +PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *m, void * ) { - return new sf2Instrument( static_cast( _data ) ); + return new sf2Instrument( static_cast( m ) ); } } - - - diff --git a/plugins/sf2_player/sf2_player.h b/plugins/sf2_player/sf2_player.h index 0d29c27e1..1dde587ad 100644 --- a/plugins/sf2_player/sf2_player.h +++ b/plugins/sf2_player/sf2_player.h @@ -36,7 +36,7 @@ #include "Knob.h" #include "LcdSpinBox.h" #include "LedCheckbox.h" -#include "fluidsynth.h" +#include "fluidsynthshims.h" #include "MemoryManager.h" class sf2InstrumentView; @@ -187,7 +187,7 @@ public: -class sf2InstrumentView : public InstrumentView +class sf2InstrumentView : public InstrumentViewFixedSize { Q_OBJECT public: diff --git a/plugins/sfxr/sfxr.cpp b/plugins/sfxr/sfxr.cpp index 02e7413bb..1aacdc12c 100644 --- a/plugins/sfxr/sfxr.cpp +++ b/plugins/sfxr/sfxr.cpp @@ -45,7 +45,6 @@ float frnd(float range) #include "Knob.h" #include "NotePlayHandle.h" #include "PixmapButton.h" -#include "templates.h" #include "ToolTip.h" #include "Song.h" #include "MidiEvent.h" @@ -54,6 +53,8 @@ float frnd(float range) #include "embed.h" +#include "plugin_export.h" + extern "C" { @@ -599,7 +600,7 @@ public: sfxrInstrumentView::sfxrInstrumentView( Instrument * _instrument, QWidget * _parent ) : - InstrumentView( _instrument, _parent ) + InstrumentViewFixedSize( _instrument, _parent ) { srand(time(NULL)); setAutoFillBackground( true ); @@ -1120,9 +1121,9 @@ extern "C" { // necessary for getting instance out of shared lib -PLUGIN_EXPORT Plugin * lmms_plugin_main( Model*, void* data ) +PLUGIN_EXPORT Plugin * lmms_plugin_main( Model* m, void* ) { - return new sfxrInstrument( static_cast( data ) ); + return new sfxrInstrument( static_cast( m ) ); } diff --git a/plugins/sfxr/sfxr.h b/plugins/sfxr/sfxr.h index 27246a1b8..20ae54c96 100644 --- a/plugins/sfxr/sfxr.h +++ b/plugins/sfxr/sfxr.h @@ -223,7 +223,7 @@ private: -class sfxrInstrumentView : public InstrumentView +class sfxrInstrumentView : public InstrumentViewFixedSize { Q_OBJECT public: diff --git a/plugins/sid/envelope.cc b/plugins/sid/envelope.cc index 7be289c53..e466bd67d 100644 --- a/plugins/sid/envelope.cc +++ b/plugins/sid/envelope.cc @@ -134,7 +134,7 @@ reg16 EnvelopeGenerator::rate_counter_period[] = { // of ENV3 with another timed loop to fully synchronize with ENV3. // // At the first period when an exponential counter period larger than one -// is used (decay or relase), one extra cycle is spent before the envelope is +// is used (decay or release), one extra cycle is spent before the envelope is // decremented. The envelope output is then delayed one cycle until the state // is changed to attack. Now one cycle less will be spent before the envelope // is incremented, and the situation is normalized. diff --git a/plugins/sid/sid_instrument.cpp b/plugins/sid/sid_instrument.cpp index ce3960832..27f874e12 100644 --- a/plugins/sid/sid_instrument.cpp +++ b/plugins/sid/sid_instrument.cpp @@ -42,6 +42,7 @@ #include "ToolTip.h" #include "embed.h" +#include "plugin_export.h" #define C64_PAL_CYCLES_PER_SEC 985248 @@ -323,7 +324,8 @@ void sidInstrument::playNote( NotePlayHandle * _n, cSID *sid = static_cast( _n->m_pluginData ); int delta_t = clockrate * frames / samplerate + 4; - short buf[frames]; + // avoid variable length array for msvc compat + short* buf = reinterpret_cast(_working_buffer + offset); unsigned char sidreg[NUMSIDREGS]; for (int c = 0; c < NUMSIDREGS; c++) @@ -428,7 +430,8 @@ void sidInstrument::playNote( NotePlayHandle * _n, if(num!=frames) printf("!!!Not enough samples\n"); - for( fpp_t frame = 0; frame < frames; ++frame ) + // loop backwards to avoid overwriting data in the short-to-float conversion + for( fpp_t frame = frames - 1; frame >= 0; frame-- ) { sample_t s = float(buf[frame])/32768.0; for( ch_cnt_t ch = 0; ch < DEFAULT_CHANNELS; ++ch ) @@ -480,7 +483,7 @@ public: sidInstrumentView::sidInstrumentView( Instrument * _instrument, QWidget * _parent ) : - InstrumentView( _instrument, _parent ) + InstrumentViewFixedSize( _instrument, _parent ) { setAutoFillBackground( true ); @@ -791,10 +794,9 @@ extern "C" { // necessary for getting instance out of shared lib -PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *, void * _data ) +PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *m, void * ) { - return( new sidInstrument( - static_cast( _data ) ) ); + return( new sidInstrument( static_cast( m ) ) ); } diff --git a/plugins/sid/sid_instrument.h b/plugins/sid/sid_instrument.h index 6128bf91c..479d09c5d 100644 --- a/plugins/sid/sid_instrument.h +++ b/plugins/sid/sid_instrument.h @@ -132,7 +132,7 @@ private: -class sidInstrumentView : public InstrumentView +class sidInstrumentView : public InstrumentViewFixedSize { Q_OBJECT public: diff --git a/plugins/stereo_enhancer/stereo_enhancer.cpp b/plugins/stereo_enhancer/stereo_enhancer.cpp index cb55213f1..2faa5846d 100644 --- a/plugins/stereo_enhancer/stereo_enhancer.cpp +++ b/plugins/stereo_enhancer/stereo_enhancer.cpp @@ -26,7 +26,7 @@ #include "stereo_enhancer.h" #include "embed.h" - +#include "plugin_export.h" extern "C" { diff --git a/plugins/stereo_matrix/stereo_matrix.cpp b/plugins/stereo_matrix/stereo_matrix.cpp index b2634e95c..a03a615ba 100644 --- a/plugins/stereo_matrix/stereo_matrix.cpp +++ b/plugins/stereo_matrix/stereo_matrix.cpp @@ -26,7 +26,7 @@ #include "stereo_matrix.h" #include "embed.h" - +#include "plugin_export.h" extern "C" { diff --git a/plugins/stk/mallets/mallets.cpp b/plugins/stk/mallets/mallets.cpp index 621d1e5c7..f770d1f58 100644 --- a/plugins/stk/mallets/mallets.cpp +++ b/plugins/stk/mallets/mallets.cpp @@ -41,7 +41,7 @@ #include "Mixer.h" #include "embed.h" - +#include "plugin_export.h" extern "C" { @@ -384,7 +384,7 @@ PluginView * malletsInstrument::instantiateView( QWidget * _parent ) malletsInstrumentView::malletsInstrumentView( malletsInstrument * _instrument, QWidget * _parent ) : - InstrumentView( _instrument, _parent ) + InstrumentViewFixedSize( _instrument, _parent ) { m_modalBarWidget = setupModalBarControls( this ); setWidgetBackground( m_modalBarWidget, "artwork" ); @@ -620,7 +620,7 @@ malletsSynth::malletsSynth( const StkFloat _pitch, { Stk::setSampleRate( _sample_rate ); Stk::setRawwavePath( QDir( ConfigManager::inst()->stkDir() ).absolutePath() - .toLatin1().constData() ); + .toLocal8Bit().constData() ); #ifndef LMMS_DEBUG Stk::showWarnings( false ); #endif @@ -670,7 +670,7 @@ malletsSynth::malletsSynth( const StkFloat _pitch, { Stk::setSampleRate( _sample_rate ); Stk::setRawwavePath( QDir( ConfigManager::inst()->stkDir() ).absolutePath() - .toLatin1().constData() ); + .toLocal8Bit().constData() ); #ifndef LMMS_DEBUG Stk::showWarnings( false ); #endif @@ -718,7 +718,7 @@ malletsSynth::malletsSynth( const StkFloat _pitch, { Stk::setSampleRate( _sample_rate ); Stk::setRawwavePath( QDir( ConfigManager::inst()->stkDir() ).absolutePath() - .toLatin1().constData() ); + .toLocal8Bit().constData() ); #ifndef LMMS_DEBUG Stk::showWarnings( false ); #endif @@ -756,9 +756,9 @@ extern "C" { // necessary for getting instance out of shared lib -Plugin * PLUGIN_EXPORT lmms_plugin_main( Model *, void * _data ) +PLUGIN_EXPORT Plugin * lmms_plugin_main( Model * m, void * ) { - return new malletsInstrument( static_cast( _data ) ); + return new malletsInstrument( static_cast( m ) ); } diff --git a/plugins/stk/mallets/mallets.h b/plugins/stk/mallets/mallets.h index 649b8ff45..6fd28d41c 100644 --- a/plugins/stk/mallets/mallets.h +++ b/plugins/stk/mallets/mallets.h @@ -85,7 +85,7 @@ public: inline ~malletsSynth() { - m_voice->noteOff( 0.0 ); + if (m_voice) {m_voice->noteOff(0.0);} delete[] m_delay; delete m_voice; } @@ -187,7 +187,7 @@ private: } ; -class malletsInstrumentView: public InstrumentView +class malletsInstrumentView: public InstrumentViewFixedSize { Q_OBJECT public: diff --git a/plugins/triple_oscillator/TripleOscillator.cpp b/plugins/triple_oscillator/TripleOscillator.cpp index 55a7ed7ed..2a1eccdd7 100644 --- a/plugins/triple_oscillator/TripleOscillator.cpp +++ b/plugins/triple_oscillator/TripleOscillator.cpp @@ -40,7 +40,7 @@ #include "ToolTip.h" #include "embed.h" - +#include "plugin_export.h" extern "C" { @@ -419,7 +419,7 @@ public: TripleOscillatorView::TripleOscillatorView( Instrument * _instrument, QWidget * _parent ) : - InstrumentView( _instrument, _parent ) + InstrumentViewFixedSize( _instrument, _parent ) { setAutoFillBackground( true ); QPalette pal; @@ -723,9 +723,9 @@ extern "C" { // necessary for getting instance out of shared lib -PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *, void * _data ) +PLUGIN_EXPORT Plugin * lmms_plugin_main( Model* model, void * ) { - return new TripleOscillator( static_cast( _data ) ); + return new TripleOscillator( static_cast( model ) ); } } diff --git a/plugins/triple_oscillator/TripleOscillator.h b/plugins/triple_oscillator/TripleOscillator.h index fb2b48a41..815fa3505 100644 --- a/plugins/triple_oscillator/TripleOscillator.h +++ b/plugins/triple_oscillator/TripleOscillator.h @@ -136,7 +136,7 @@ private: -class TripleOscillatorView : public InstrumentView +class TripleOscillatorView : public InstrumentViewFixedSize { Q_OBJECT public: diff --git a/plugins/vestige/CMakeLists.txt b/plugins/vestige/CMakeLists.txt index 21803a924..823c03202 100644 --- a/plugins/vestige/CMakeLists.txt +++ b/plugins/vestige/CMakeLists.txt @@ -1,6 +1,5 @@ IF(LMMS_SUPPORT_VST) INCLUDE(BuildPlugin) - INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/../vst_base") LINK_DIRECTORIES("${CMAKE_CURRENT_BINARY_DIR}/..") IF(LMMS_BUILD_LINUX) LINK_LIBRARIES(-Wl,--enable-new-dtags) @@ -10,7 +9,6 @@ IF(LMMS_SUPPORT_VST) SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${PLUGIN_DIR}") ENDIF() BUILD_PLUGIN(vestige vestige.cpp vestige.h MOCFILES vestige.h EMBEDDED_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.png") - TARGET_LINK_LIBRARIES(vestige -lvstbase) - ADD_DEPENDENCIES(vestige vstbase) + TARGET_LINK_LIBRARIES(vestige vstbase) ENDIF(LMMS_SUPPORT_VST) diff --git a/plugins/vestige/vestige.cpp b/plugins/vestige/vestige.cpp index e1869a74e..fc61a2484 100644 --- a/plugins/vestige/vestige.cpp +++ b/plugins/vestige/vestige.cpp @@ -22,8 +22,14 @@ * */ +#include + +#include "VstPlugin.h" + #include "vestige.h" +#include + #include #include #include @@ -39,17 +45,19 @@ #include "gui_templates.h" #include "InstrumentPlayHandle.h" #include "InstrumentTrack.h" -#include "VstPlugin.h" +#include "LocaleHelper.h" #include "MainWindow.h" #include "Mixer.h" #include "GuiApplication.h" #include "PixmapButton.h" #include "SampleBuffer.h" +#include "Song.h" #include "StringPairDrag.h" #include "TextFloat.h" #include "ToolTip.h" #include "FileDialog.h" + #include "embed.h" @@ -57,7 +65,7 @@ extern "C" { -Plugin::Descriptor PLUGIN_EXPORT vestige_plugin_descriptor = +Plugin::Descriptor Q_DECL_EXPORT vestige_plugin_descriptor = { STRINGIFY( PLUGIN_NAME ), "VeSTige", @@ -74,6 +82,62 @@ Plugin::Descriptor PLUGIN_EXPORT vestige_plugin_descriptor = } +class vstSubWin : public SubWindow +{ +public: + vstSubWin( QWidget * _parent ) : + SubWindow( _parent ) + { + setAttribute( Qt::WA_DeleteOnClose, false ); + setWindowFlags( Qt::WindowCloseButtonHint ); + } + + virtual ~vstSubWin() + { + } + + virtual void closeEvent( QCloseEvent * e ) + { + // ignore close-events - for some reason otherwise the VST GUI + // remains hidden when re-opening + hide(); + e->ignore(); + } +}; + + +class VstInstrumentPlugin : public VstPlugin +{ +public: + using VstPlugin::VstPlugin; + + void createUI( QWidget *parent ) override + { + Q_UNUSED(parent); + if ( !hasEditor() ) { + return; + } + if ( embedMethod() != "none" ) { + m_pluginSubWindow.reset(new vstSubWin( gui->mainWindow()->workspace() )); + VstPlugin::createUI( m_pluginSubWindow.get() ); + m_pluginSubWindow->setWidget(pluginWidget()); + } else { + VstPlugin::createUI( nullptr ); + } + } + + /// Overwrite editor() to return the sub window instead of the embed widget + /// itself. This makes toggleUI() and related functions toggle the + /// sub window's visibility. + QWidget* editor() override + { + return m_pluginSubWindow.get(); + } +private: + unique_ptr m_pluginSubWindow; +}; + + QPixmap * VestigeInstrumentView::s_artwork = NULL; QPixmap * manageVestigeInstrumentView::s_artwork = NULL; @@ -122,12 +186,24 @@ vestigeInstrument::~vestigeInstrument() void vestigeInstrument::loadSettings( const QDomElement & _this ) { - loadFile( _this.attribute( "plugin" ) ); + QString plugin = _this.attribute( "plugin" ); + if( plugin.isEmpty() ) + { + return; + } + + loadFile( plugin ); m_pluginMutex.lock(); if( m_plugin != NULL ) { m_plugin->loadSettings( _this ); + if ( _this.attribute( "guivisible" ).toInt() ) { + m_plugin->showUI(); + } else { + m_plugin->hideUI(); + } + const QMap & dump = m_plugin->parameterDump(); paramCount = dump.size(); char paramStr[35]; @@ -143,11 +219,12 @@ void vestigeInstrument::loadSettings( const QDomElement & _this ) if( !( knobFModel[ i ]->isAutomated() || knobFModel[ i ]->controllerConnection() ) ) { - knobFModel[ i ]->setValue( ( s_dumpValues.at( 2 )).toFloat() ); - knobFModel[ i ]->setInitValue( ( s_dumpValues.at( 2 )).toFloat() ); + knobFModel[ i ]->setValue(LocaleHelper::toFloat(s_dumpValues.at(2))); + knobFModel[ i ]->setInitValue(LocaleHelper::toFloat(s_dumpValues.at(2))); } - connect( knobFModel[i], SIGNAL( dataChanged() ), this, SLOT( setParameter() ) ); + connect( knobFModel[i], &FloatModel::dataChanged, this, + [this, i]() { setParameter( knobFModel[i] ); }, Qt::DirectConnection); } } m_pluginMutex.unlock(); @@ -156,10 +233,8 @@ void vestigeInstrument::loadSettings( const QDomElement & _this ) -void vestigeInstrument::setParameter( void ) +void vestigeInstrument::setParameter( Model * action ) { - - Model *action = qobject_cast(sender()); int knobUNID = action->displayName().toInt(); if ( m_plugin != NULL ) { @@ -268,7 +343,7 @@ void vestigeInstrument::loadFile( const QString & _file ) } m_pluginMutex.lock(); - m_plugin = new VstPlugin( m_pluginDLL ); + m_plugin = new VstInstrumentPlugin( m_pluginDLL ); if( m_plugin->failed() ) { m_pluginMutex.unlock(); @@ -279,6 +354,7 @@ void vestigeInstrument::loadFile( const QString & _file ) return; } + m_plugin->createUI(nullptr); m_plugin->showUI(); if( set_ch_name ) @@ -298,14 +374,12 @@ void vestigeInstrument::loadFile( const QString & _file ) void vestigeInstrument::play( sampleFrame * _buf ) { - m_pluginMutex.lock(); + if (!m_pluginMutex.tryLock(Engine::getSong()->isExporting() ? -1 : 0)) {return;} const fpp_t frames = Engine::mixer()->framesPerPeriod(); if( m_plugin == NULL ) { - BufferManager::clear( _buf, frames ); - m_pluginMutex.unlock(); return; } @@ -394,7 +468,7 @@ PluginView * vestigeInstrument::instantiateView( QWidget * _parent ) VestigeInstrumentView::VestigeInstrumentView( Instrument * _instrument, QWidget * _parent ) : - InstrumentView( _instrument, _parent ), + InstrumentViewFixedSize( _instrument, _parent ), lastPosInMenu (0) { if( s_artwork == NULL ) @@ -550,7 +624,7 @@ void VestigeInstrumentView::updateMenu( void ) QMenu * to_menu = m_selPresetButton->menu(); to_menu->clear(); - QAction *presetActions[list1.size()]; + QVector presetActions(list1.size()); for (int i = 0; i < list1.size(); i++) { presetActions[i] = new QAction(this); @@ -826,7 +900,7 @@ void VestigeInstrumentView::paintEvent( QPaintEvent * ) manageVestigeInstrumentView::manageVestigeInstrumentView( Instrument * _instrument, QWidget * _parent, vestigeInstrument * m_vi2 ) : - InstrumentView( _instrument, _parent ) + InstrumentViewFixedSize( _instrument, _parent ) { m_vi = m_vi2; m_vi->m_scrollArea = new QScrollArea( this ); @@ -900,11 +974,14 @@ manageVestigeInstrumentView::manageVestigeInstrumentView( Instrument * _instrume if( !hasKnobModel ) { sprintf( paramStr, "%d", i); - m_vi->knobFModel[ i ] = new FloatModel( (s_dumpValues.at( 2 )).toFloat(), + m_vi->knobFModel[ i ] = new FloatModel( LocaleHelper::toFloat(s_dumpValues.at(2)), 0.0f, 1.0f, 0.01f, castModel(), tr( paramStr ) ); } - connect( m_vi->knobFModel[i], SIGNAL( dataChanged() ), this, SLOT( setParameter() ) ); - vstKnobs[i] ->setModel( m_vi->knobFModel[i] ); + + FloatModel * model = m_vi->knobFModel[i]; + connect( model, &FloatModel::dataChanged, this, + [this, model]() { setParameter( model ); }, Qt::DirectConnection); + vstKnobs[i] ->setModel( model ); } int i = 0; @@ -961,7 +1038,7 @@ void manageVestigeInstrumentView::syncPlugin( void ) { sprintf( paramStr, "param%d", i ); s_dumpValues = dump[ paramStr ].split( ":" ); - f_value = ( s_dumpValues.at( 2 ) ).toFloat(); + f_value = LocaleHelper::toFloat(s_dumpValues.at(2)); m_vi->knobFModel[ i ]->setAutomatedValue( f_value ); m_vi->knobFModel[ i ]->setInitValue( f_value ); } @@ -1035,10 +1112,8 @@ manageVestigeInstrumentView::~manageVestigeInstrumentView() -void manageVestigeInstrumentView::setParameter( void ) +void manageVestigeInstrumentView::setParameter( Model * action ) { - - Model *action = qobject_cast(sender()); int knobUNID = action->displayName().toInt(); if ( m_vi->m_plugin != NULL ) { @@ -1101,9 +1176,9 @@ extern "C" { // necessary for getting instance out of shared lib -PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *, void * _data ) +Q_DECL_EXPORT Plugin * lmms_plugin_main( Model *m, void * ) { - return new vestigeInstrument( static_cast( _data ) ); + return new vestigeInstrument( static_cast( m ) ); } diff --git a/plugins/vestige/vestige.h b/plugins/vestige/vestige.h index 2c007efc0..7090fee1e 100644 --- a/plugins/vestige/vestige.h +++ b/plugins/vestige/vestige.h @@ -29,14 +29,13 @@ #include #include -#include #include #include "Instrument.h" #include "InstrumentView.h" #include "Note.h" #include "Knob.h" - +#include "SubWindow.h" #include "AutomatableModel.h" @@ -73,7 +72,7 @@ public: virtual PluginView * instantiateView( QWidget * _parent ); protected slots: - void setParameter( void ); + void setParameter( Model * action ); void handleConfigChange( QString cls, QString attr, QString value ); void reloadPlugin(); @@ -98,7 +97,7 @@ private: } ; -class manageVestigeInstrumentView : public InstrumentView +class manageVestigeInstrumentView : public InstrumentViewFixedSize { Q_OBJECT public: @@ -109,7 +108,7 @@ public: protected slots: void syncPlugin( void ); void displayAutomatedOnly( void ); - void setParameter( void ); + void setParameter( Model * action ); void closeWindow(); @@ -134,7 +133,7 @@ private: } ; -class VestigeInstrumentView : public InstrumentView +class VestigeInstrumentView : public InstrumentViewFixedSize { Q_OBJECT public: diff --git a/plugins/vibed/nine_button_selector.cpp b/plugins/vibed/nine_button_selector.cpp index 0c48c66c9..edcfc2f51 100644 --- a/plugins/vibed/nine_button_selector.cpp +++ b/plugins/vibed/nine_button_selector.cpp @@ -52,8 +52,8 @@ nineButtonSelector::nineButtonSelector( QPixmap _button0_on, int _x, int _y, QWidget * _parent ): QWidget( _parent ), - IntModelView( new nineButtonSelectorModel(0, 8, _default, NULL, - QString::null, true ), this ) + IntModelView( new nineButtonSelectorModel(0, 8, _default, NULL, + QString(), true ), this ) { setFixedSize( 50, 50 ); move( _x, _y ); diff --git a/plugins/vibed/vibed.cpp b/plugins/vibed/vibed.cpp index 95a2c428a..c66366082 100644 --- a/plugins/vibed/vibed.cpp +++ b/plugins/vibed/vibed.cpp @@ -35,12 +35,11 @@ #include "CaptionMenu.h" #include "Oscillator.h" #include "string_container.h" -#include "templates.h" #include "volume.h" #include "Song.h" #include "embed.h" - +#include "plugin_export.h" extern "C" { @@ -350,7 +349,7 @@ PluginView * vibed::instantiateView( QWidget * _parent ) vibedView::vibedView( Instrument * _instrument, QWidget * _parent ) : - InstrumentView( _instrument, _parent ) + InstrumentViewFixedSize( _instrument, _parent ) { setAutoFillBackground( true ); QPalette pal; @@ -682,9 +681,9 @@ extern "C" { // necessary for getting instance out of shared lib -PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *, void * _data ) +PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *m, void * ) { - return( new vibed( static_cast( _data ) ) ); + return( new vibed( static_cast( m ) ) ); } diff --git a/plugins/vibed/vibed.h b/plugins/vibed/vibed.h index 9e175c4cc..b1c33f4b7 100644 --- a/plugins/vibed/vibed.h +++ b/plugins/vibed/vibed.h @@ -82,7 +82,7 @@ private: -class vibedView : public InstrumentView +class vibedView : public InstrumentViewFixedSize { Q_OBJECT public: diff --git a/plugins/vibed/vibrating_string.cpp b/plugins/vibed/vibrating_string.cpp index a2080a69c..14a666bbd 100644 --- a/plugins/vibed/vibrating_string.cpp +++ b/plugins/vibed/vibrating_string.cpp @@ -24,7 +24,6 @@ #include #include "vibrating_string.h" -#include "templates.h" #include "interpolation.h" #include "Mixer.h" #include "Engine.h" @@ -56,7 +55,7 @@ vibratingString::vibratingString( float _pitch, int pick = static_cast( ceil( string_length * _pick ) ); - if( not _state ) + if( ! _state ) { m_impulse = new float[string_length]; resample( _impulse, _len, string_length ); @@ -145,9 +144,9 @@ void vibratingString::resample( float *_src, f_cnt_t _src_frames, _dst_frames; const float frac_pos = src_frame_float - static_cast( src_frame_float ); - const f_cnt_t src_frame = tLimit( - static_cast( src_frame_float ), - 1, _src_frames - 3 ); + const f_cnt_t src_frame = qBound( + 1, static_cast( src_frame_float ), + _src_frames - 3 ); m_impulse[frame] = cubicInterpolate( _src[src_frame - 1], _src[src_frame + 0], diff --git a/plugins/vibed/vibrating_string.h b/plugins/vibed/vibrating_string.h index 06358501f..3739d19a9 100644 --- a/plugins/vibed/vibrating_string.h +++ b/plugins/vibed/vibrating_string.h @@ -121,7 +121,7 @@ private: float r; float offset; - if( not _state ) + if( ! _state ) { for( int i = 0; i < _pick; i++ ) { diff --git a/plugins/vst_base/CMakeLists.txt b/plugins/vst_base/CMakeLists.txt index b0a478232..873ed5f8e 100644 --- a/plugins/vst_base/CMakeLists.txt +++ b/plugins/vst_base/CMakeLists.txt @@ -1,93 +1,50 @@ -IF(LMMS_SUPPORT_VST) +IF(NOT LMMS_SUPPORT_VST) + RETURN() +ENDIF() INCLUDE(BuildPlugin) +INCLUDE(ExternalProject) -IF(LMMS_BUILD_WIN32) - ADD_DEFINITIONS(-DPTW32_STATIC_LIB) - ADD_EXECUTABLE(RemoteVstPlugin "${CMAKE_CURRENT_SOURCE_DIR}/RemoteVstPlugin.cpp") +# These variables are not meant to be used normally, except packaging +SET(REMOTE_VST_PLUGIN_FILEPATH_32 "32/RemoteVstPlugin32" CACHE STRING "Relative file path to RemoteVstPlugin32") +SET(REMOTE_VST_PLUGIN_FILEPATH_64 "RemoteVstPlugin64" CACHE STRING "Relative file path to RemoteVstPlugin64") - TARGET_LINK_LIBRARIES(RemoteVstPlugin Qt5::Core) - TARGET_LINK_LIBRARIES(RemoteVstPlugin -lpthread -lgdi32 -lws2_32) - SET_TARGET_PROPERTIES(RemoteVstPlugin PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -O0") - ADD_CUSTOM_COMMAND(TARGET RemoteVstPlugin POST_BUILD COMMAND "${STRIP}" "$") - INSTALL(TARGETS RemoteVstPlugin RUNTIME DESTINATION "${PLUGIN_DIR}") +ADD_SUBDIRECTORY(vstbase) - # FIXME: 32-bit VST fails on MSYS - IF(LMMS_BUILD_WIN64 AND NOT LMMS_BUILD_MSYS) - # build 32 bit version of RemoteVstPlugin for Win64 so we can load - # 32 bit VST plugins - ADD_SUBDIRECTORY(Win64) - ENDIF(LMMS_BUILD_WIN64 AND NOT LMMS_BUILD_MSYS) -ENDIF(LMMS_BUILD_WIN32) - -SET(REMOTE_VST_PLUGIN_FILEPATH "RemoteVstPlugin" CACHE STRING "Relative file path to RemoteVstPlugin") - -INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/src/3rdparty/qt5-x11embed/src/") -ADD_DEFINITIONS(-DREMOTE_VST_PLUGIN_FILEPATH="${REMOTE_VST_PLUGIN_FILEPATH}") -BUILD_PLUGIN(vstbase vst_base.cpp VstPlugin.cpp VstPlugin.h communication.h MOCFILES VstPlugin.h) - -IF(LMMS_BUILD_LINUX) - TARGET_LINK_LIBRARIES(vstbase qx11embedcontainer) -ENDIF() - -IF(LMMS_BUILD_LINUX AND NOT WANT_VST_NOWINE) - -IF(LMMS_HOST_X86_64) - SET(EXTRA_FLAGS -m32) - IF(WINE_LIBRARY_FIX) - SET(EXTRA_FLAGS ${EXTRA_FLAGS} -nodefaultlibs ${WINE_LIBRARY_FIX}wine/libwinecrt0.a -L${WINE_LIBRARY_FIX}wine/ -luser32 -lkernel32 -lgdi32) - ENDIF() -ENDIF(LMMS_HOST_X86_64) - -SET(WINE_CXX_FLAGS "" CACHE STRING "Extra flags passed to wineg++") - -STRING(REPLACE "include/wine" "include" WINE_INCLUDE_BASE_DIR ${WINE_INCLUDE_DIR}) -STRING(REPLACE "lib/libwine.so" "lib" WINE_LIBRARY_DIR ${WINE_LIBRARY}) -STRING(REPLACE " " ";" WINE_BUILD_FLAGS ${CMAKE_CXX_FLAGS} " " ${CMAKE_EXE_LINKER_FLAGS} " " ${WINE_CXX_FLAGS}) - -SET(WINE_CXX_ARGS - -I${CMAKE_BINARY_DIR} - -I${CMAKE_SOURCE_DIR}/include - -I${WINE_INCLUDE_BASE_DIR} - -I${WINE_INCLUDE_DIR}/windows - -L${WINE_LIBRARY_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/RemoteVstPlugin.cpp - -std=c++0x - -mwindows -lpthread ${EXTRA_FLAGS} -fno-omit-frame-pointer - ${WINE_BUILD_FLAGS} - -o ../RemoteVstPlugin +SET(EXTERNALPROJECT_ARGS + SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/RemoteVstPlugin" + #INSTALL_COMMAND "" + BUILD_ALWAYS ON + # Skip the install step. + INSTALL_COMMAND "" ) -# winegcc fails if winebuild is not in path -GET_FILENAME_COMPONENT(WINE_BINDIR ${WINE_CXX} PATH) -FIND_PROGRAM(WINEBUILD winebuild NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH) -IF(NOT WINEBUILD) - IF(CMAKE_VERSION VERSION_LESS 3.1) - MESSAGE(WARNING "winebuild is not in PATH. Building RemoteVstPlugin may fail.") - ELSE() - SET(WINE_CXX_ARGS -E env PATH=$ENV{PATH}:${WINE_BINDIR} ${WINE_CXX} ${WINE_CXX_ARGS}) - SET(WINE_CXX "${CMAKE_COMMAND}") - ENDIF() -ENDIF() +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(ENV{PATH} "$ENV{PATH}:${WINE_BINDIR}") - -ADD_CUSTOM_COMMAND( - SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/RemoteVstPlugin.cpp" - COMMAND export - ARGS "PATH=$PATH:${WINE_BINDIR}" - COMMAND ${WINE_CXX} - ARGS ${WINE_CXX_ARGS} - # Ensure correct file extension - COMMAND sh -c "mv ../RemoteVstPlugin.exe ../RemoteVstPlugin || true" - TARGET vstbase - OUTPUTS ../RemoteVstPlugin - VERBATIM +SET(EXTERNALPROJECT_CMAKE_ARGS + "-DBUILD_WITH_EXTERNALPROJECT=ON" ) -SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES ../RemoteVstPlugin.exe.so) -INSTALL(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/../RemoteVstPlugin" "${CMAKE_CURRENT_BINARY_DIR}/../RemoteVstPlugin.exe.so" DESTINATION "${PLUGIN_DIR}") -ENDIF(LMMS_BUILD_LINUX AND NOT WANT_VST_NOWINE) +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() - -ENDIF(LMMS_SUPPORT_VST) +# build 32 bit version of RemoteVstPlugin +IF(WANT_VST_32) + INCLUDE("${CMAKE_CURRENT_LIST_DIR}/RemoteVstPlugin32.cmake") +ENDIF() +# build 64 bit version of RemoteVstPlugin +IF(WANT_VST_64) + INCLUDE("${CMAKE_CURRENT_LIST_DIR}/RemoteVstPlugin64.cmake") +ENDIF() diff --git a/plugins/vst_base/RemoteVstPlugin.cpp b/plugins/vst_base/RemoteVstPlugin.cpp index 71ebf74c0..5b4bbbd9b 100644 --- a/plugins/vst_base/RemoteVstPlugin.cpp +++ b/plugins/vst_base/RemoteVstPlugin.cpp @@ -34,10 +34,6 @@ #include "RemotePlugin.h" -#ifdef LMMS_HAVE_PTHREAD_H -#include -#endif - #ifdef LMMS_HAVE_FCNTL_H #include #endif @@ -63,6 +59,13 @@ #define USE_WS_PREFIX #include +#ifdef USE_MINGW_THREADS_REPLACEMENT +# include +#else +# include +#endif + +#include #include #include #include @@ -88,6 +91,7 @@ struct ERect #include "lmms_basics.h" #include "Midi.h" #include "communication.h" +#include "IoHelper.h" #include "VstSyncData.h" @@ -117,8 +121,28 @@ class RemoteVstPlugin; RemoteVstPlugin * __plugin = NULL; HWND __MessageHwnd = NULL; +DWORD __processingThreadId = 0; +//Returns the last Win32 error, in string format. Returns an empty string if there is no error. +std::string GetErrorAsString(DWORD errorMessageID) +{ + //Get the error message, if any. + if(errorMessageID == 0) + return std::string(); //No error message has been recorded + + LPSTR messageBuffer = nullptr; + size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL); + + std::string message(messageBuffer, size); + + //Free the buffer. + LocalFree(messageBuffer); + + return message; +} + class RemoteVstPlugin : public RemotePluginClient { @@ -134,6 +158,8 @@ public: void init( const std::string & _plugin_file ); void initEditor(); + void showEditor(); + void hideEditor(); void destroyEditor(); virtual void process( const sampleFrame * _in, sampleFrame * _out ); @@ -144,6 +170,7 @@ public: // set given sample-rate for plugin virtual void updateSampleRate() { + SuspendPlugin suspend( this ); pluginDispatch( effSetSampleRate, 0, 0, NULL, (float) sampleRate() ); } @@ -151,9 +178,20 @@ public: // set given buffer-size for plugin virtual void updateBufferSize() { + SuspendPlugin suspend( this ); pluginDispatch( effSetBlockSize, 0, bufferSize() ); } + void setResumed( bool resumed ) + { + m_resumed = resumed; + pluginDispatch( effMainsChanged, 0, resumed ? 1 : 0 ); + } + + inline bool isResumed() const + { + return m_resumed; + } inline bool isInitialized() const { @@ -236,21 +274,21 @@ public: } // has to be called as soon as input- or output-count changes - void updateInOutCount(); + int updateInOutCount(); inline void lockShm() { - pthread_mutex_lock( &m_shmLock ); + m_shmLock.lock(); } inline bool tryLockShm() { - return pthread_mutex_trylock( &m_shmLock ) == 0; + return m_shmLock.try_lock(); } inline void unlockShm() { - pthread_mutex_unlock( &m_shmLock ); + m_shmLock.unlock(); } inline bool isShmValid() @@ -293,8 +331,8 @@ public: static DWORD WINAPI processingThread( LPVOID _param ); static bool setupMessageWindow(); static DWORD WINAPI guiEventLoop(); - static LRESULT CALLBACK messageWndProc( HWND hwnd, UINT uMsg, - WPARAM wParam, LPARAM lParam ); + static LRESULT CALLBACK wndProc( HWND hwnd, UINT uMsg, + WPARAM wParam, LPARAM lParam ); private: @@ -306,8 +344,26 @@ private: ClosePlugin } ; + struct SuspendPlugin { + SuspendPlugin( RemoteVstPlugin * plugin ) : + m_plugin( plugin ), + m_resumed( plugin->isResumed() ) + { + if( m_resumed ) { m_plugin->setResumed( false ); } + } + + ~SuspendPlugin() + { + if( m_resumed ) { m_plugin->setResumed( true ); } + } + + private: + RemoteVstPlugin * m_plugin; + bool m_resumed; + }; + // callback used by plugin for being able to communicate with it's host - static intptr_t hostCallback( AEffect * _effect, int32_t _opcode, + static intptr_t VST_CALL_CONV hostCallback( AEffect * _effect, int32_t _opcode, int32_t _index, intptr_t _value, void * _ptr, float _opt ); @@ -336,6 +392,7 @@ private: int m_windowHeight; bool m_initialized; + bool m_resumed; bool m_processing; @@ -346,7 +403,7 @@ private: float * * m_inputs; float * * m_outputs; - pthread_mutex_t m_shmLock; + std::mutex m_shmLock; bool m_shmValid; typedef std::vector VstMidiEventList; @@ -359,8 +416,9 @@ private: // host to plugin synchronisation data structure struct in { - float lastppqPos; - float m_Timestamp; + double lastppqPos; + double m_Timestamp; + int32_t m_lastFlags; } ; in * m_in; @@ -387,12 +445,12 @@ RemoteVstPlugin::RemoteVstPlugin( const char * socketPath ) : m_windowWidth( 0 ), m_windowHeight( 0 ), m_initialized( false ), + m_resumed( false ), m_processing( false ), m_messageList(), m_shouldGiveIdle( false ), m_inputs( NULL ), m_outputs( NULL ), - m_shmLock(), m_shmValid( false ), m_midiEvents(), m_bpm( 0 ), @@ -402,8 +460,6 @@ RemoteVstPlugin::RemoteVstPlugin( const char * socketPath ) : m_shmID( -1 ), m_vstSyncData( NULL ) { - pthread_mutex_init( &m_shmLock, NULL ); - __plugin = this; #ifndef USE_QT_SHMEM @@ -442,12 +498,14 @@ RemoteVstPlugin::RemoteVstPlugin( const char * socketPath ) : m_vstSyncData->ppqPos = 0; m_vstSyncData->isCycle = false; m_vstSyncData->hasSHM = false; + m_vstSyncData->m_playbackJumped = false; m_vstSyncData->m_sampleRate = sampleRate(); } m_in = ( in* ) new char[ sizeof( in ) ]; m_in->lastppqPos = 0; m_in->m_Timestamp = -1; + m_in->m_lastFlags = 0; // process until we have loaded the plugin while( 1 ) @@ -467,7 +525,7 @@ RemoteVstPlugin::RemoteVstPlugin( const char * socketPath ) : RemoteVstPlugin::~RemoteVstPlugin() { destroyEditor(); - pluginDispatch( effMainsChanged, 0, 0 ); + setResumed( false ); pluginDispatch( effClose ); #ifndef USE_QT_SHMEM // detach shared memory segment @@ -493,8 +551,6 @@ RemoteVstPlugin::~RemoteVstPlugin() delete[] m_inputs; delete[] m_outputs; - - pthread_mutex_destroy( &m_shmLock ); } @@ -507,27 +563,28 @@ bool RemoteVstPlugin::processMessage( const message & _m ) switch( _m.id ) { case IdShowUI: - initEditor(); + showEditor(); return true; case IdHideUI: - destroyEditor(); + hideEditor(); return true; case IdToggleUI: - if( m_window ) + if( m_window && IsWindowVisible( m_window ) ) { - destroyEditor(); + hideEditor(); } else { - initEditor(); + showEditor(); } return true; case IdIsUIVisible: + bool visible = m_window && IsWindowVisible( m_window ); sendMessage( message( IdIsUIVisible ) - .addInt( m_window ? 1 : 0 ) ); + .addInt( visible ? 1 : 0 ) ); return true; } } @@ -644,7 +701,7 @@ void RemoteVstPlugin::init( const std::string & _plugin_file ) pluginDispatch( effSetProgram, 0, 0 ); */ // request rate and blocksize - pluginDispatch( effMainsChanged, 0, 1 ); + setResumed( true ); debugMessage( "creating editor\n" ); initEditor(); @@ -675,11 +732,12 @@ void RemoteVstPlugin::init( const std::string & _plugin_file ) -static void close_check( int fd ) +static void close_check( FILE* fp ) { - if( close( fd ) ) + if (!fp) {return;} + if( fclose( fp ) ) { - perror( "close" ); + perror( "fclose" ); } } @@ -709,7 +767,7 @@ void RemoteVstPlugin::initEditor() dwStyle = WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX; } - m_window = CreateWindowEx( 0, "LVSL", pluginName(), + m_window = CreateWindowEx( WS_EX_APPWINDOW, "LVSL", pluginName(), dwStyle, 0, 0, 10, 10, NULL, NULL, hInst, NULL ); if( m_window == NULL ) @@ -727,15 +785,13 @@ void RemoteVstPlugin::initEditor() m_windowWidth = er->right - er->left; m_windowHeight = er->bottom - er->top; - SetWindowPos( m_window, 0, 0, 0, m_windowWidth + 8, - m_windowHeight + 26, SWP_NOACTIVATE | + RECT windowSize = { 0, 0, m_windowWidth, m_windowHeight }; + AdjustWindowRect( &windowSize, dwStyle, false ); + SetWindowPos( m_window, 0, 0, 0, windowSize.right - windowSize.left, + windowSize.bottom - windowSize.top, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER ); pluginDispatch( effEditTop ); - if (! EMBED) { - ShowWindow( m_window, SW_SHOWNORMAL ); - } - #ifdef LMMS_BUILD_LINUX m_windowID = (intptr_t) GetProp( m_window, "__wine_x11_whole_window" ); #else @@ -747,6 +803,26 @@ void RemoteVstPlugin::initEditor() +void RemoteVstPlugin::showEditor() { + if( !EMBED && !HEADLESS && m_window ) + { + ShowWindow( m_window, SW_SHOWNORMAL ); + } +} + + + + +void RemoteVstPlugin::hideEditor() { + if( !EMBED && !HEADLESS && m_window ) + { + ShowWindow( m_window, SW_HIDE ); + } +} + + + + void RemoteVstPlugin::destroyEditor() { if( m_window == NULL ) @@ -765,17 +841,14 @@ void RemoteVstPlugin::destroyEditor() bool RemoteVstPlugin::load( const std::string & _plugin_file ) { - if( ( m_libInst = LoadLibrary( _plugin_file.c_str() ) ) == NULL ) + if( ( m_libInst = LoadLibraryW( toWString(_plugin_file).c_str() ) ) == NULL ) { - // give VstPlugin class a chance to start 32 bit version of RemoteVstPlugin - if( GetLastError() == ERROR_BAD_EXE_FORMAT ) - { - sendMessage( IdVstBadDllFormat ); - } + DWORD error = GetLastError(); + debugMessage( "LoadLibrary failed: " + GetErrorAsString(error) ); return false; } - typedef AEffect * ( __stdcall * mainEntryPointer ) + typedef AEffect * ( VST_CALL_CONV * mainEntryPointer ) ( audioMasterCallback ); mainEntryPointer mainEntry = (mainEntryPointer) GetProcAddress( m_libInst, "VSTPluginMain" ); @@ -838,6 +911,14 @@ void RemoteVstPlugin::process( const sampleFrame * _in, sampleFrame * _out ) static char eventsBuffer[sizeof( VstEvents ) + sizeof( VstMidiEvent * ) * MIDI_EVENT_BUFFER_COUNT]; static VstMidiEvent vme[MIDI_EVENT_BUFFER_COUNT]; + // first sort events chronologically, since some plugins + // (e.g. Sinnah) can hang if they're out of order + std::stable_sort( m_midiEvents.begin(), m_midiEvents.end(), + []( const VstMidiEvent &a, const VstMidiEvent &b ) + { + return a.deltaFrames < b.deltaFrames; + } ); + VstEvents* events = (VstEvents *) eventsBuffer; events->reserved = 0; events->numEvents = m_midiEvents.size(); @@ -1047,13 +1128,19 @@ void RemoteVstPlugin::saveChunkToFile( const std::string & _file ) const int len = pluginDispatch( 23, 0, 0, &chunk ); if( len > 0 ) { - int fd = open( _file.c_str(), O_WRONLY | O_BINARY ); - if ( ::write( fd, chunk, len ) != len ) + 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, "Error saving chunk to file.\n" ); } - close_check( fd ); + close_check( fp ); } } } @@ -1212,7 +1299,13 @@ void RemoteVstPlugin::savePreset( const std::string & _file ) if (!isPreset &&!chunky) uIntToFile = (unsigned int) m_plugin->numPrograms; pBank->numPrograms = endian_swap( uIntToFile ); - FILE * stream = fopen( _file.c_str(), "w" ); + 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 ) { @@ -1264,7 +1357,13 @@ void RemoteVstPlugin::loadPresetFile( const std::string & _file ) unsigned int * pLen = new unsigned int[ 1 ]; unsigned int len = 0; sBank * pBank = (sBank*) new char[ sizeof( sBank ) ]; - FILE * stream = fopen( _file.c_str(), "r" ); + 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" ); @@ -1365,12 +1464,18 @@ void RemoteVstPlugin::loadChunkFromFile( const std::string & _file, int _len ) { char * chunk = new char[_len]; - const int fd = open( _file.c_str(), O_RDONLY | O_BINARY ); - if ( ::read( fd, chunk, _len ) != _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" ); } - close_check( fd ); + close_check( fp ); pluginDispatch( effSetChunk, 0, _len, chunk ); @@ -1380,8 +1485,21 @@ void RemoteVstPlugin::loadChunkFromFile( const std::string & _file, int _len ) -void RemoteVstPlugin::updateInOutCount() +int RemoteVstPlugin::updateInOutCount() { + if( inputCount() == RemotePluginClient::inputCount() && + outputCount() == RemotePluginClient::outputCount() ) + { + return 1; + } + + if( GetCurrentThreadId() == __processingThreadId ) + { + debugMessage( "Plugin requested I/O change from processing " + "thread. Request denied; stability may suffer.\n" ); + return 0; + } + lockShm(); setShmIsValid( false ); @@ -1409,6 +1527,8 @@ void RemoteVstPlugin::updateInOutCount() { m_outputs = new float * [outputCount()]; } + + return 1; } @@ -1514,16 +1634,25 @@ intptr_t RemoteVstPlugin::hostCallback( AEffect * _effect, int32_t _opcode, __plugin->m_in->m_Timestamp ) { _timeInfo.ppqPos = __plugin->m_vstSyncData->ppqPos; - _timeInfo.flags |= kVstTransportChanged; __plugin->m_in->lastppqPos = __plugin->m_vstSyncData->ppqPos; __plugin->m_in->m_Timestamp = __plugin->m_vstSyncData->ppqPos; } else if( __plugin->m_vstSyncData->isPlaying ) { - __plugin->m_in->lastppqPos += ( - __plugin->m_vstSyncData->hasSHM ? - __plugin->m_vstSyncData->m_bpm : - __plugin->m_bpm ) / (float)10340; + if( __plugin->m_vstSyncData->hasSHM ) + { + __plugin->m_in->lastppqPos += + __plugin->m_vstSyncData->m_bpm / 60.0 + * __plugin->m_vstSyncData->m_bufferSize + / __plugin->m_vstSyncData->m_sampleRate; + } + else + { + __plugin->m_in->lastppqPos += + __plugin->m_bpm / 60.0 + * __plugin->bufferSize() + / __plugin->sampleRate(); + } _timeInfo.ppqPos = __plugin->m_in->lastppqPos; } // _timeInfo.ppqPos = __plugin->m_vstSyncData->ppqPos; @@ -1541,11 +1670,15 @@ intptr_t RemoteVstPlugin::hostCallback( AEffect * _effect, int32_t _opcode, _timeInfo.flags |= kVstBarsValid; -#ifdef LMMS_BUILD_WIN64 - return (long long) &_timeInfo; -#else - return (long) &_timeInfo; -#endif + if( ( _timeInfo.flags & ( kVstTransportPlaying | kVstTransportCycleActive ) ) != + ( __plugin->m_in->m_lastFlags & ( kVstTransportPlaying | kVstTransportCycleActive ) ) + || __plugin->m_vstSyncData->m_playbackJumped ) + { + _timeInfo.flags |= kVstTransportChanged; + } + __plugin->m_in->m_lastFlags = _timeInfo.flags; + + return (intptr_t) &_timeInfo; case audioMasterProcessEvents: SHOW_CALLBACK( "amc: audioMasterProcessEvents\n" ); @@ -1553,10 +1686,9 @@ intptr_t RemoteVstPlugin::hostCallback( AEffect * _effect, int32_t _opcode, return 0; case audioMasterIOChanged: - __plugin->updateInOutCount(); SHOW_CALLBACK( "amc: audioMasterIOChanged\n" ); - // numInputs and/or numOutputs has changed - return 0; + // numInputs, numOutputs, and/or latency has changed + return __plugin->updateInOutCount(); #ifdef OLD_VST_SDK case audioMasterWantMidi: @@ -1643,6 +1775,7 @@ intptr_t RemoteVstPlugin::hostCallback( AEffect * _effect, int32_t _opcode, #endif case audioMasterSizeWindow: + { SHOW_CALLBACK( "amc: audioMasterSizeWindow\n" ); if( __plugin->m_window == 0 ) { @@ -1650,8 +1783,13 @@ intptr_t RemoteVstPlugin::hostCallback( AEffect * _effect, int32_t _opcode, } __plugin->m_windowWidth = _index; __plugin->m_windowHeight = _value; - SetWindowPos( __plugin->m_window, 0, 0, 0, - _index + 8, _value + 26, + HWND window = __plugin->m_window; + DWORD dwStyle = GetWindowLongPtr( window, GWL_STYLE ); + RECT windowSize = { 0, 0, (int) _index, (int) _value }; + AdjustWindowRect( &windowSize, dwStyle, false ); + SetWindowPos( window, 0, 0, 0, + windowSize.right - windowSize.left, + windowSize.bottom - windowSize.top, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER ); __plugin->sendMessage( @@ -1659,6 +1797,7 @@ intptr_t RemoteVstPlugin::hostCallback( AEffect * _effect, int32_t _opcode, addInt( __plugin->m_windowWidth ). addInt( __plugin->m_windowHeight ) ); return 1; + } case audioMasterGetSampleRate: SHOW_CALLBACK( "amc: audioMasterGetSampleRate\n" ); @@ -1839,12 +1978,17 @@ void RemoteVstPlugin::processUIThreadMessages() DWORD WINAPI RemoteVstPlugin::processingThread( LPVOID _param ) { + __processingThreadId = GetCurrentThreadId(); + RemoteVstPlugin * _this = static_cast( _param ); RemotePluginClient::message m; while( ( m = _this->receiveMessage() ).id != IdQuit ) { - if( m.id == IdStartProcessing || m.id == IdMidiEvent ) + if( m.id == IdStartProcessing + || m.id == IdMidiEvent + || m.id == IdVstSetParameter + || m.id == IdVstSetTempo ) { _this->processMessage( m ); } @@ -1884,8 +2028,6 @@ bool RemoteVstPlugin::setupMessageWindow() __MessageHwnd = CreateWindowEx( 0, "LVSL", "dummy", 0, 0, 0, 0, 0, NULL, NULL, hInst, NULL ); - SetWindowLongPtr( __MessageHwnd, GWLP_WNDPROC, - reinterpret_cast( RemoteVstPlugin::messageWndProc ) ); // install GUI update timer SetTimer( __MessageHwnd, 1000, 50, NULL ); @@ -1910,7 +2052,7 @@ DWORD WINAPI RemoteVstPlugin::guiEventLoop() -LRESULT CALLBACK RemoteVstPlugin::messageWndProc( HWND hwnd, UINT uMsg, +LRESULT CALLBACK RemoteVstPlugin::wndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { if( uMsg == WM_TIMER && __plugin->isInitialized() ) @@ -1947,9 +2089,9 @@ LRESULT CALLBACK RemoteVstPlugin::messageWndProc( HWND hwnd, UINT uMsg, break; } } - else if( uMsg == WM_SYSCOMMAND && wParam == SC_CLOSE ) + else if( uMsg == WM_SYSCOMMAND && (wParam & 0xfff0) == SC_CLOSE ) { - __plugin->destroyEditor(); + __plugin->hideEditor(); return 0; } @@ -1971,14 +2113,7 @@ int main( int _argc, char * * _argv ) return -1; } -#ifdef LMMS_BUILD_WIN32 -#ifndef __WINPTHREADS_VERSION - // (non-portable) initialization of statically linked pthread library - pthread_win32_process_attach_np(); - pthread_win32_thread_attach_np(); -#endif -#endif - + OleInitialize(nullptr); #ifdef LMMS_BUILD_LINUX #ifdef LMMS_HAVE_SCHED_H // try to set realtime-priority @@ -2004,7 +2139,7 @@ int main( int _argc, char * * _argv ) WNDCLASS wc; wc.style = CS_HREDRAW | CS_VREDRAW; - wc.lpfnWndProc = DefWindowProc; + wc.lpfnWndProc = RemoteVstPlugin::wndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInst; @@ -2086,14 +2221,7 @@ int main( int _argc, char * * _argv ) delete __plugin; - -#ifdef LMMS_BUILD_WIN32 -#ifndef __WINPTHREADS_VERSION - pthread_win32_thread_detach_np(); - pthread_win32_process_detach_np(); -#endif -#endif - + OleUninitialize(); return 0; } diff --git a/plugins/vst_base/RemoteVstPlugin/CMakeLists.txt b/plugins/vst_base/RemoteVstPlugin/CMakeLists.txt new file mode 100644 index 000000000..f4023fd42 --- /dev/null +++ b/plugins/vst_base/RemoteVstPlugin/CMakeLists.txt @@ -0,0 +1,93 @@ +cmake_minimum_required(VERSION 3.1) +project(RemoteVstPlugin + LANGUAGES CXX) +set(CMAKE_CXX_STANDARD 11) + +include(CheckCXXPreprocessor) +include(CheckCXXSourceCompiles) + +CHECK_CXX_DEFINE(IS_WIN "_WIN32") +CHECK_CXX_DEFINE(IS_WIN64 "_WIN64") +CHECK_CXX_DEFINE(IS_MINGW "__MINGW32__") + +if(NOT IS_WIN) + message(FATAL_ERROR "Toolchain used does not target windows.") +ENDIF() + +if(IS_WIN64 OR CMAKE_SIZEOF_VOID_P EQUAL 8) + set(BITNESS 64) +else() + set(BITNESS 32) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/32") +endif() + +FOREACH( OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES} ) + STRING(TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG) + SET("CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG}" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") +ENDFOREACH() + +set(EXE_NAME RemoteVstPlugin${BITNESS}) +add_executable(${EXE_NAME} WIN32 + ../RemoteVstPlugin.cpp +) + +target_link_libraries(${EXE_NAME} ole32) + +target_include_directories(${EXE_NAME} + PRIVATE + "${LMMS_SOURCE_DIR}/plugins/vst_base/common" + "${LMMS_SOURCE_DIR}/include" + "${LMMS_BINARY_DIR}" +) + +# Workaround for missing WinMain +if(MSVC) + set_property(TARGET ${EXE_NAME} + APPEND + PROPERTY LINK_FLAGS "/entry:mainCRTStartup" +) +endif() + + +if(WIN32) + find_package(Qt5Core REQUIRED) + target_link_libraries(${EXE_NAME} Qt5::Core) +endif() + +if(IS_MINGW) + SET(CMAKE_REQUIRED_FLAGS "-std=c++11") + + CHECK_CXX_SOURCE_COMPILES(" + #include + int main(int argc, const char* argv[]) { + std::mutex m; + return 0; + } + " HAS_STD_MUTEX) + + if(NOT HAS_STD_MUTEX) + target_include_directories(${EXE_NAME} PRIVATE + "${LMMS_SOURCE_DIR}/src/3rdparty/mingw-std-threads") + target_compile_definitions(${EXE_NAME} PRIVATE + -DUSE_MINGW_THREADS_REPLACEMENT) + endif() +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 new file mode 100644 index 000000000..cba9a26c8 --- /dev/null +++ b/plugins/vst_base/RemoteVstPlugin32.cmake @@ -0,0 +1,80 @@ +# 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) +ELSEIF(LMMS_BUILD_WIN64 AND MSVC) + 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${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. + #So for the moment, we'll allow the built. + IF(NOT (IS_DIRECTORY ${QT_32_PREFIX} AND EXISTS ${QT_32_PREFIX}/bin/qmake.exe)) + MESSAGE(WARNING "No Qt 32 bit installation found at ${QT_32_PREFIX}. If you're using VCPKG you can ignore this message if you've built x86-windows version of qt5") + ENDIF() + + ExternalProject_Add(RemoteVstPlugin32 + "${EXTERNALPROJECT_ARGS}" + CMAKE_GENERATOR "${LMMS_MSVC_GENERATOR}" + CMAKE_GENERATOR_PLATFORM Win32 + #CMAKE_GENERATOR_TOOLSET "${CMAKE_GENERATOR_TOOLSET}" + CMAKE_ARGS + "${EXTERNALPROJECT_CMAKE_ARGS}" + "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}" + "-DCMAKE_PREFIX_PATH=${QT_32_PREFIX}" + ) + + INSTALL_EXTERNAL_PROJECT(RemoteVstPlugin32) +ELSEIF(LMMS_BUILD_LINUX) + # Use winegcc + INCLUDE(CheckWineGcc) + CheckWineGcc(32 "${WINEGCC}" WINEGCC_WORKING) + IF(NOT WINEGCC_WORKING) + MESSAGE(WARNING "winegcc fails to complie 32-bit binaries, please make sure you have 32-bit GCC libraries") + RETURN() + ENDIF() + ExternalProject_Add(RemoteVstPlugin32 + "${EXTERNALPROJECT_ARGS}" + CMAKE_ARGS + "${EXTERNALPROJECT_CMAKE_ARGS}" + "-DCMAKE_CXX_COMPILER=${WINEGCC}" + "-DCMAKE_CXX_FLAGS=-m32" + ) + + INSTALL(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/../32/RemoteVstPlugin32" "${CMAKE_CURRENT_BINARY_DIR}/../32/RemoteVstPlugin32.exe.so" DESTINATION "${PLUGIN_DIR}/32") + +ELSEIF(CMAKE_TOOLCHAIN_FILE_32) + ExternalProject_Add(RemoteVstPlugin32 + "${EXTERNALPROJECT_ARGS}" + CMAKE_ARGS + "${EXTERNALPROJECT_CMAKE_ARGS}" + "-DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH_32}" + "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE_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() +ENDIF() + diff --git a/plugins/vst_base/RemoteVstPlugin64.cmake b/plugins/vst_base/RemoteVstPlugin64.cmake new file mode 100644 index 000000000..65b33a162 --- /dev/null +++ b/plugins/vst_base/RemoteVstPlugin64.cmake @@ -0,0 +1,18 @@ +IF(LMMS_BUILD_WIN64) + ADD_SUBDIRECTORY(RemoteVstPlugin) +ELSEIF(LMMS_BUILD_LINUX) + INCLUDE(CheckWineGcc) + CheckWineGcc(64 "${WINEGCC}" WINEGCC_WORKING) + IF(NOT WINEGCC_WORKING) + MESSAGE(WARNING "winegcc fails to compile 64-bit binaries, please make sure you have 64-bit GCC libraries") + RETURN() + ENDIF() + ExternalProject_Add(RemoteVstPlugin64 + "${EXTERNALPROJECT_ARGS}" + CMAKE_ARGS + "${EXTERNALPROJECT_CMAKE_ARGS}" + "-DCMAKE_CXX_COMPILER=${WINEGCC}" + "-DCMAKE_CXX_FLAGS=-m64" + ) + INSTALL(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/../RemoteVstPlugin64" "${CMAKE_CURRENT_BINARY_DIR}/../RemoteVstPlugin64.exe.so" DESTINATION "${PLUGIN_DIR}") +ENDIF() diff --git a/plugins/vst_base/VstPlugin.cpp b/plugins/vst_base/VstPlugin.cpp index 5c7504dd1..8d86f576f 100644 --- a/plugins/vst_base/VstPlugin.cpp +++ b/plugins/vst_base/VstPlugin.cpp @@ -24,6 +24,9 @@ #include "VstPlugin.h" +#include "communication.h" + +#include #include #include #include @@ -34,55 +37,87 @@ #include #ifdef LMMS_BUILD_LINUX -# if QT_VERSION < 0x050000 -# include -# include -# else -# include "X11EmbedContainer.h" -# include -# endif +# include +# include "X11EmbedContainer.h" #endif -#if QT_VERSION >= 0x050000 -# include -#endif +#include #include #ifdef LMMS_BUILD_WIN32 +# ifndef NOMINMAX +# define NOMINMAX +# endif + # include # include #endif #include "ConfigManager.h" #include "GuiApplication.h" +#include "LocaleHelper.h" #include "MainWindow.h" #include "Mixer.h" #include "Song.h" -#include "templates.h" #include "FileDialog.h" -class vstSubWin : public QMdiSubWindow +#ifdef LMMS_BUILD_LINUX +# include +#endif + +namespace PE +{ +// Utilities for reading PE file machine type +// See specification at https://msdn.microsoft.com/library/windows/desktop/ms680547(v=vs.85).aspx + +// Work around name conflict +#ifdef i386 +# undef i386 +#endif + +enum class MachineType : uint16_t +{ + unknown = 0x0, + amd64 = 0x8664, + i386 = 0x14c, +}; + +class FileInfo { public: - vstSubWin( QWidget * _parent ) : - QMdiSubWindow( _parent ) + FileInfo(QString filePath) + : m_file(filePath) { - setAttribute( Qt::WA_DeleteOnClose, false ); + m_file.open(QFile::ReadOnly); + m_map = m_file.map(0, m_file.size()); + if (m_map == nullptr) { + throw std::runtime_error("Cannot map file"); + } + } + ~FileInfo() + { + m_file.unmap(m_map); } - virtual ~vstSubWin() + MachineType machineType() { + int32_t peOffset = qFromLittleEndian(* reinterpret_cast(m_map + 0x3C)); + uchar* peSignature = m_map + peOffset; + if (memcmp(peSignature, "PE\0\0", 4)) { + throw std::runtime_error("Invalid PE file"); + } + uchar * coffHeader = peSignature + 4; + uint16_t machineType = qFromLittleEndian(* reinterpret_cast(coffHeader)); + return static_cast(machineType); } - virtual void closeEvent( QCloseEvent * e ) - { - // ignore close-events - for some reason otherwise the VST GUI - // remains hidden when re-opening - hide(); - e->ignore(); - } -} ; +private: + QFile m_file; + uchar* m_map; +}; + +} VstPlugin::VstPlugin( const QString & _plugin ) : @@ -91,25 +126,42 @@ VstPlugin::VstPlugin( const QString & _plugin ) : m_embedMethod( gui ? ConfigManager::inst()->vstEmbedMethod() : "headless" ), - m_badDllFormat( false ), m_version( 0 ), m_currentProgram() { + if( QDir::isRelativePath( m_plugin ) ) + { + m_plugin = ConfigManager::inst()->vstDir() + m_plugin; + } + setSplittedChannels( true ); - tryLoad( REMOTE_VST_PLUGIN_FILEPATH ); -#ifdef LMMS_BUILD_WIN64 - if( m_badDllFormat ) - { - m_badDllFormat = false; - tryLoad( "32/RemoteVstPlugin32" ); + PE::MachineType machineType; + try { + PE::FileInfo peInfo(m_plugin); + machineType = peInfo.machineType(); + } catch (std::runtime_error& e) { + qCritical() << "Error while determining PE file's machine type: " << e.what(); + machineType = PE::MachineType::unknown; + } + + switch(machineType) + { + case PE::MachineType::amd64: + tryLoad( REMOTE_VST_PLUGIN_FILEPATH_64 ); // Default: RemoteVstPlugin64 + break; + case PE::MachineType::i386: + tryLoad( REMOTE_VST_PLUGIN_FILEPATH_32 ); // Default: 32/RemoteVstPlugin32 + break; + default: + m_failed = true; + return; } -#endif setTempo( Engine::getSong()->getTempo() ); connect( Engine::getSong(), SIGNAL( tempoChanged( bpm_t ) ), - this, SLOT( setTempo( bpm_t ) ) ); + this, SLOT( setTempo( bpm_t ) ), Qt::DirectConnection ); connect( Engine::mixer(), SIGNAL( sampleRateChanged() ), this, SLOT( updateSampleRate() ) ); @@ -124,7 +176,6 @@ VstPlugin::VstPlugin( const QString & _plugin ) : VstPlugin::~VstPlugin() { - delete m_pluginSubWindow; delete m_pluginWidget; } @@ -155,16 +206,7 @@ void VstPlugin::tryLoad( const QString &remoteVstPluginExecutable ) default: break; } sendMessage( message( IdVstSetLanguage ).addInt( hlang ) ); - - - QString p = m_plugin; - if( QFileInfo( p ).dir().isRelative() ) - { - p = ConfigManager::inst()->vstDir() + p; - } - - - sendMessage( message( IdVstLoadPlugin ).addString( QSTR_TO_STDSTR( p ) ) ); + sendMessage( message( IdVstLoadPlugin ).addString( QSTR_TO_STDSTR( m_plugin ) ) ); waitForInitDone(); @@ -174,39 +216,11 @@ void VstPlugin::tryLoad( const QString &remoteVstPluginExecutable ) -void VstPlugin::hideEditor() -{ - QWidget * w = pluginWidget(); - if( w ) - { - w->hide(); - } -} - - - - -void VstPlugin::toggleEditor() -{ - QWidget * w = pluginWidget(); - if( w ) - { - w->setVisible( !w->isVisible() ); - } -} - - - - void VstPlugin::loadSettings( const QDomElement & _this ) { - if( _this.attribute( "guivisible" ).toInt() ) + if( _this.hasAttribute( "program" ) ) { - showUI(); - } - else - { - hideUI(); + setProgram( _this.attribute( "program" ).toInt() ); } const int num_params = _this.attribute( "numparams" ).toInt(); @@ -228,11 +242,6 @@ void VstPlugin::loadSettings( const QDomElement & _this ) } setParameterDump( dump ); } - - if( _this.hasAttribute( "program" ) ) - { - setProgram( _this.attribute( "program" ).toInt() ); - } } @@ -286,7 +295,7 @@ void VstPlugin::toggleUI() } else if (pluginWidget()) { - toggleEditor(); + toggleEditorVisibility(); } } @@ -351,7 +360,7 @@ void VstPlugin::setParameterDump( const QMap & _pdump ) { ( *it ).section( ':', 0, 0 ).toInt(), "", - ( *it ).section( ':', 2, -1 ).toFloat() + LocaleHelper::toFloat((*it).section(':', 2, -1)) } ; m.addInt( item.index ); m.addString( item.shortLabel ); @@ -362,21 +371,9 @@ void VstPlugin::setParameterDump( const QMap & _pdump ) unlock(); } -QWidget *VstPlugin::pluginWidget(bool _top_widget) +QWidget *VstPlugin::pluginWidget() { - if ( m_embedMethod == "none" || !m_pluginWidget ) - { - return nullptr; - } - - if ( _top_widget && m_pluginWidget->parentWidget() == m_pluginSubWindow ) - { - return m_pluginSubWindow; - } - else - { - return m_pluginWidget; - } + return m_pluginWidget; } @@ -386,12 +383,26 @@ bool VstPlugin::processMessage( const message & _m ) { switch( _m.id ) { - case IdVstBadDllFormat: - m_badDllFormat = true; - break; - case IdVstPluginWindowID: m_pluginWindowID = _m.getInt(); + if( m_embedMethod == "none" + && ConfigManager::inst()->value( + "ui", "vstalwaysontop" ).toInt() ) + { +#ifdef LMMS_BUILD_WIN32 + // We're changing the owner, not the parent, + // so this is legal despite MSDN's warning + SetWindowLongPtr( (HWND)(intptr_t) m_pluginWindowID, + GWLP_HWNDPARENT, + (LONG_PTR) gui->mainWindow()->winId() ); +#endif + +#ifdef LMMS_BUILD_LINUX + XSetTransientForHint( QX11Info::display(), + m_pluginWindowID, + gui->mainWindow()->winId() ); +#endif + } break; case IdVstPluginEditorGeometry: @@ -458,6 +469,10 @@ bool VstPlugin::processMessage( const message & _m ) } +QWidget *VstPlugin::editor() +{ + return m_pluginWidget; +} void VstPlugin::openPreset( ) @@ -579,15 +594,10 @@ void VstPlugin::showUI() } else if ( m_embedMethod != "headless" ) { - if (! pluginWidget()) { - createUI( NULL, false ); - } - - QWidget * w = pluginWidget(); - if( w ) - { - w->show(); + if (! editor()) { + qWarning() << "VstPlugin::showUI called before VstPlugin::createUI"; } + toggleEditorVisibility( true ); } } @@ -599,7 +609,7 @@ void VstPlugin::hideUI() } else if ( pluginWidget() != nullptr ) { - hideEditor(); + toggleEditorVisibility( false ); } } @@ -654,22 +664,39 @@ QByteArray VstPlugin::saveChunk() return a; } -void VstPlugin::createUI( QWidget * parent, bool isEffect ) +void VstPlugin::toggleEditorVisibility( int visible ) { + QWidget* w = editor(); + if ( ! w ) { + return; + } + + if ( visible < 0 ) { + visible = ! w->isVisible(); + } + w->setVisible( visible ); +} + +void VstPlugin::createUI( QWidget * parent ) +{ + if ( m_pluginWidget ) { + qWarning() << "VstPlugin::createUI called twice"; + m_pluginWidget->setParent( parent ); + return; + } + if( m_pluginWindowID == 0 ) { return; } QWidget* container = nullptr; - m_pluginSubWindow = new vstSubWin( gui->mainWindow()->workspace() ); - auto sw = m_pluginSubWindow.data(); #if QT_VERSION >= 0x050100 if (m_embedMethod == "qt" ) { QWindow* vw = QWindow::fromWinId(m_pluginWindowID); - container = QWidget::createWindowContainer(vw, sw ); + container = QWidget::createWindowContainer(vw, parent ); container->installEventFilter(this); } else #endif @@ -708,7 +735,11 @@ void VstPlugin::createUI( QWidget * parent, bool isEffect ) #ifdef LMMS_BUILD_LINUX if (m_embedMethod == "xembed" ) { - QX11EmbedContainer * embedContainer = new QX11EmbedContainer( sw ); + if (parent) + { + parent->setAttribute(Qt::WA_NativeWindow); + } + QX11EmbedContainer * embedContainer = new QX11EmbedContainer( parent ); connect(embedContainer, SIGNAL(clientIsEmbedded()), this, SLOT(handleClientEmbed())); embedContainer->embedClient( m_pluginWindowID ); container = embedContainer; @@ -716,31 +747,13 @@ void VstPlugin::createUI( QWidget * parent, bool isEffect ) #endif { qCritical() << "Unknown embed method" << m_embedMethod; - delete m_pluginSubWindow; return; } container->setFixedSize( m_pluginGeometry ); container->setWindowTitle( name() ); - if( parent == NULL ) - { - m_pluginWidget = container; - - sw->setWidget(container); - - if( isEffect ) - { - sw->setAttribute( Qt::WA_TranslucentBackground ); - sw->setWindowFlags( Qt::FramelessWindowHint ); - } - else - { - sw->setWindowFlags( Qt::WindowCloseButtonHint ); - } - }; - - container->setFixedSize( m_pluginGeometry ); + m_pluginWidget = container; } bool VstPlugin::eventFilter(QObject *obj, QEvent *event) diff --git a/plugins/vst_base/VstPlugin.h b/plugins/vst_base/VstPlugin.h index f3d6bea8e..26e7fec36 100644 --- a/plugins/vst_base/VstPlugin.h +++ b/plugins/vst_base/VstPlugin.h @@ -33,12 +33,14 @@ #include #include "JournallingObject.h" -#include "communication.h" +#include "RemotePlugin.h" + +#include "vstbase_export.h" class vstSubWin; -class PLUGIN_EXPORT VstPlugin : public RemotePlugin, public JournallingObject +class VSTBASE_EXPORT VstPlugin : public RemotePlugin, public JournallingObject { Q_OBJECT public: @@ -47,15 +49,17 @@ public: void tryLoad( const QString &remoteVstPluginExecutable ); - virtual bool processMessage( const message & _m ); + bool processMessage( const message & _m ) override; inline bool hasEditor() const { return m_pluginWindowID != 0; } - void hideEditor(); - void toggleEditor(); + /// Same as pluginWidget(), but can be overwritten in sub-classes to modify + /// behavior the UI. This is used in VstInstrumentPlugin to wrap the VST UI + /// in a QMdiSubWindow + virtual QWidget* editor(); inline const QString & name() const { @@ -93,20 +97,19 @@ public: void setParameterDump( const QMap & _pdump ); - QWidget * pluginWidget( bool _top_widget = true ); + 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"; } - void toggleUI() override; - void createUI( QWidget *parent, bool isEffect ); - bool eventFilter(QObject *obj, QEvent *event); + virtual void createUI(QWidget *parent); + bool eventFilter(QObject *obj, QEvent *event) override; QString embedMethod() const; @@ -123,6 +126,7 @@ public slots: void showUI() override; void hideUI() override; + void toggleUI() override; void handleClientEmbed(); @@ -130,15 +134,14 @@ private: void loadChunk( const QByteArray & _chunk ); QByteArray saveChunk(); + void toggleEditorVisibility(int visible = -1); + QString m_plugin; QPointer m_pluginWidget; - QPointer m_pluginSubWindow; int m_pluginWindowID; QSize m_pluginGeometry; const QString m_embedMethod; - bool m_badDllFormat; - QString m_name; int m_version; QString m_vendorString; diff --git a/plugins/vst_base/Win64/CMakeLists.txt b/plugins/vst_base/Win64/CMakeLists.txt deleted file mode 100644 index 39b9b5a9b..000000000 --- a/plugins/vst_base/Win64/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -INCLUDE_DIRECTORIES("${CMAKE_BINARY_DIR}" "${CMAKE_SOURCE_DIR}/include") -SET(CMAKE_CXX_COMPILER "${CMAKE_CXX_COMPILER32}") - -ADD_EXECUTABLE(RemoteVstPlugin32 "${CMAKE_CURRENT_SOURCE_DIR}/../RemoteVstPlugin.cpp") - -SET(QTCORE "Qt5Core") -TARGET_LINK_LIBRARIES(RemoteVstPlugin32 -l${QTCORE} -lpthread -lgdi32 -lws2_32) - -ADD_CUSTOM_COMMAND(TARGET RemoteVstPlugin32 POST_BUILD COMMAND "${STRIP}" "$") -SET_TARGET_PROPERTIES(RemoteVstPlugin32 PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -O0") - -INSTALL(TARGETS RemoteVstPlugin32 RUNTIME DESTINATION "${PLUGIN_DIR}/32") -INSTALL(FILES "${MINGW_PREFIX32}/bin/${QTCORE}.dll" "${MINGW_PREFIX32}/bin/zlib1.dll" "${MINGW_PREFIX32}/${CMAKE_SYSTEM_PROCESSOR32}-w64-mingw32/bin/libwinpthread-1.dll" - DESTINATION "${PLUGIN_DIR}/32") - diff --git a/plugins/vst_base/communication.h b/plugins/vst_base/communication.h index bacf43c1e..756fd7557 100644 --- a/plugins/vst_base/communication.h +++ b/plugins/vst_base/communication.h @@ -27,8 +27,6 @@ #ifndef _COMMUNICATION_H #define _COMMUNICATION_H -#include "RemotePlugin.h" - struct VstParameterDumpItem @@ -72,7 +70,6 @@ enum VstRemoteMessageIDs // remoteVstPlugin -> vstPlugin IdVstFailedLoadingPlugin, - IdVstBadDllFormat, IdVstPluginWindowID, IdVstPluginEditorGeometry, IdVstPluginName, diff --git a/plugins/vst_base/vst_base.cpp b/plugins/vst_base/vst_base.cpp index 1c1770abe..0ca1159a2 100644 --- a/plugins/vst_base/vst_base.cpp +++ b/plugins/vst_base/vst_base.cpp @@ -26,12 +26,12 @@ #include "Plugin.h" #include "embed.h" - +#include "vstbase_export.h" extern "C" { -Plugin::Descriptor PLUGIN_EXPORT vstbase_plugin_descriptor = +Plugin::Descriptor VSTBASE_EXPORT vstbase_plugin_descriptor = { STRINGIFY( PLUGIN_NAME ), "VST Base", diff --git a/plugins/vst_base/vstbase/CMakeLists.txt b/plugins/vst_base/vstbase/CMakeLists.txt new file mode 100644 index 000000000..bd5f98b56 --- /dev/null +++ b/plugins/vst_base/vstbase/CMakeLists.txt @@ -0,0 +1,17 @@ +ADD_DEFINITIONS(-DREMOTE_VST_PLUGIN_FILEPATH_32="${REMOTE_VST_PLUGIN_FILEPATH_32}") +ADD_DEFINITIONS(-DREMOTE_VST_PLUGIN_FILEPATH_64="${REMOTE_VST_PLUGIN_FILEPATH_64}") + +BUILD_PLUGIN(vstbase + ../vst_base.cpp ../VstPlugin.cpp ../VstPlugin.h ../communication.h + MOCFILES ../VstPlugin.h + EXPORT_BASE_NAME vstbase + LINK SHARED +) + +TARGET_INCLUDE_DIRECTORIES(vstbase + PUBLIC ../ +) + +IF(LMMS_BUILD_LINUX) + TARGET_LINK_LIBRARIES(vstbase qx11embedcontainer) +ENDIF() diff --git a/plugins/watsyn/Watsyn.cpp b/plugins/watsyn/Watsyn.cpp index c0a952fb8..a5af401cc 100644 --- a/plugins/watsyn/Watsyn.cpp +++ b/plugins/watsyn/Watsyn.cpp @@ -28,7 +28,6 @@ #include "base64.h" #include "Engine.h" #include "InstrumentTrack.h" -#include "templates.h" #include "ToolTip.h" #include "Song.h" #include "lmms_math.h" @@ -36,6 +35,7 @@ #include "interpolation.h" #include "embed.h" +#include "plugin_export.h" extern "C" { @@ -666,7 +666,7 @@ void WatsynInstrument::updateWaveB2() WatsynView::WatsynView( Instrument * _instrument, QWidget * _parent ) : - InstrumentView( _instrument, _parent ) + InstrumentViewFixedSize( _instrument, _parent ) { setAutoFillBackground( true ); QPalette pal; @@ -1278,9 +1278,9 @@ extern "C" { // necessary for getting instance out of shared lib -PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *, void * _data ) +PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *m, void * ) { - return( new WatsynInstrument( static_cast( _data ) ) ); + return( new WatsynInstrument( static_cast( m ) ) ); } diff --git a/plugins/watsyn/Watsyn.h b/plugins/watsyn/Watsyn.h index e52b7bb75..079e532e4 100644 --- a/plugins/watsyn/Watsyn.h +++ b/plugins/watsyn/Watsyn.h @@ -293,7 +293,7 @@ private: }; -class WatsynView : public InstrumentView +class WatsynView : public InstrumentViewFixedSize { Q_OBJECT public: diff --git a/plugins/waveshaper/waveshaper.cpp b/plugins/waveshaper/waveshaper.cpp index 047cd05d1..3f9d3e19f 100644 --- a/plugins/waveshaper/waveshaper.cpp +++ b/plugins/waveshaper/waveshaper.cpp @@ -29,6 +29,7 @@ #include "embed.h" #include "interpolation.h" +#include "plugin_export.h" extern "C" { diff --git a/plugins/zynaddsubfx/CMakeLists.txt b/plugins/zynaddsubfx/CMakeLists.txt index ff9d7219d..f9cc4efd3 100644 --- a/plugins/zynaddsubfx/CMakeLists.txt +++ b/plugins/zynaddsubfx/CMakeLists.txt @@ -3,7 +3,7 @@ INCLUDE(BuildPlugin) set(CMAKE_POSITION_INDEPENDENT_CODE ON) # definitions for ZynAddSubFX -IF(LMMS_BUILD_LINUX OR LMMS_BUILD_APPLE OR LMMS_BUILD_OPENBSD) +IF(LMMS_BUILD_LINUX OR LMMS_BUILD_APPLE OR LMMS_BUILD_OPENBSD OR LMMS_BUILD_FREEBSD) FIND_PACKAGE(X11) INCLUDE_DIRECTORIES(${X11_INCLUDE_DIR}) ADD_DEFINITIONS(-DOS_LINUX) @@ -20,7 +20,11 @@ IF(LMMS_HOST_X86 OR LMMS_HOST_X86_64) ENDIF(LMMS_HOST_X86 OR LMMS_HOST_X86_64) # build ZynAddSubFX with full optimizations -SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -Wno-misleading-indentation -Wno-write-strings -Wno-deprecated-declarations -fpermissive") +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -Wno-write-strings -Wno-deprecated-declarations -fpermissive") + +IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND NOT "${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS "6.0.0") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-misleading-indentation") +ENDIF() IF(LMMS_BUILD_WIN32) # link system-libraries @@ -122,11 +126,6 @@ ELSE() ENDIF() TARGET_LINK_LIBRARIES(ZynAddSubFxCore zynaddsubfx_nio ${FFTW3F_LIBRARIES} ${QT_LIBRARIES} -lz -lpthread) -# required libs for debug msys builds -IF(LMMS_BUILD_MSYS AND CMAKE_BUILD_TYPE STREQUAL "Debug") - TARGET_LINK_LIBRARIES(ZynAddSubFxCore QtCore4 QtGui4 QtXml4) -ENDIF() - TARGET_LINK_LIBRARIES(ZynAddSubFxCore Qt5::Widgets Qt5::Xml) IF(LMMS_BUILD_WIN32) @@ -163,6 +162,12 @@ 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") +ENDIF(LMMS_BUILD_WIN32) # Remove useless dependencies from FLTK. Use fltk-config to avoid static library # in older environments diff --git a/plugins/zynaddsubfx/ZynAddSubFx.cpp b/plugins/zynaddsubfx/ZynAddSubFx.cpp index 7ec345ff0..429948e75 100644 --- a/plugins/zynaddsubfx/ZynAddSubFx.cpp +++ b/plugins/zynaddsubfx/ZynAddSubFx.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -40,6 +41,7 @@ #include "InstrumentPlayHandle.h" #include "InstrumentTrack.h" #include "gui_templates.h" +#include "Song.h" #include "StringPairDrag.h" #include "RemoteZynAddSubFx.h" #include "LocalZynAddSubFx.h" @@ -47,8 +49,7 @@ #include "ControllerConnection.h" #include "embed.h" - - +#include "plugin_export.h" extern "C" { @@ -121,13 +122,20 @@ ZynAddSubFxInstrument::ZynAddSubFxInstrument( { initPlugin(); - connect( &m_portamentoModel, SIGNAL( dataChanged() ), this, SLOT( updatePortamento() ) ); - connect( &m_filterFreqModel, SIGNAL( dataChanged() ), this, SLOT( updateFilterFreq() ) ); - connect( &m_filterQModel, SIGNAL( dataChanged() ), this, SLOT( updateFilterQ() ) ); - connect( &m_bandwidthModel, SIGNAL( dataChanged() ), this, SLOT( updateBandwidth() ) ); - connect( &m_fmGainModel, SIGNAL( dataChanged() ), this, SLOT( updateFmGain() ) ); - connect( &m_resCenterFreqModel, SIGNAL( dataChanged() ), this, SLOT( updateResCenterFreq() ) ); - connect( &m_resBandwidthModel, SIGNAL( dataChanged() ), this, SLOT( updateResBandwidth() ) ); + connect( &m_portamentoModel, SIGNAL( dataChanged() ), + this, SLOT( updatePortamento() ), Qt::DirectConnection ); + connect( &m_filterFreqModel, SIGNAL( dataChanged() ), + this, SLOT( updateFilterFreq() ), Qt::DirectConnection ); + connect( &m_filterQModel, SIGNAL( dataChanged() ), + this, SLOT( updateFilterQ() ), Qt::DirectConnection ); + connect( &m_bandwidthModel, SIGNAL( dataChanged() ), + this, SLOT( updateBandwidth() ), Qt::DirectConnection ); + connect( &m_fmGainModel, SIGNAL( dataChanged() ), + this, SLOT( updateFmGain() ), Qt::DirectConnection ); + connect( &m_resCenterFreqModel, SIGNAL( dataChanged() ), + this, SLOT( updateResCenterFreq() ), Qt::DirectConnection ); + connect( &m_resBandwidthModel, SIGNAL( dataChanged() ), + this, SLOT( updateResBandwidth() ), Qt::DirectConnection ); // now we need a play-handle which cares for calling play() InstrumentPlayHandle * iph = new InstrumentPlayHandle( this, _instrumentTrack ); @@ -137,7 +145,7 @@ ZynAddSubFxInstrument::ZynAddSubFxInstrument( this, SLOT( reloadPlugin() ) ); connect( instrumentTrack()->pitchRangeModel(), SIGNAL( dataChanged() ), - this, SLOT( updatePitchRange() ) ); + this, SLOT( updatePitchRange() ), Qt::DirectConnection ); } @@ -240,7 +248,6 @@ void ZynAddSubFxInstrument::loadSettings( const QDomElement & _this ) doc.appendChild( doc.importNode( data, true ) ); QTemporaryFile tf; - tf.setAutoRemove( false ); if( tf.open() ) { QByteArray a = doc.toString( 0 ).toUtf8(); @@ -284,6 +291,7 @@ void ZynAddSubFxInstrument::loadSettings( const QDomElement & _this ) emit settingsChanged(); } + emit instrumentTrack()->pitchModel()->dataChanged(); } @@ -326,7 +334,7 @@ QString ZynAddSubFxInstrument::nodeName() const void ZynAddSubFxInstrument::play( sampleFrame * _buf ) { - m_pluginMutex.lock(); + if (!m_pluginMutex.tryLock(Engine::getSong()->isExporting() ? -1 : 0)) {return;} if( m_remotePlugin ) { m_remotePlugin->process( NULL, _buf ); @@ -489,7 +497,7 @@ PluginView * ZynAddSubFxInstrument::instantiateView( QWidget * _parent ) ZynAddSubFxView::ZynAddSubFxView( Instrument * _instrument, QWidget * _parent ) : - InstrumentView( _instrument, _parent ) + InstrumentViewFixedSize( _instrument, _parent ) { setAutoFillBackground( true ); QPalette pal; @@ -642,8 +650,6 @@ void ZynAddSubFxView::toggleUI() connect( model->m_remotePlugin, SIGNAL( clickedCloseButton() ), m_toggleUIButton, SLOT( toggle() ) ); } - - ControllerConnection::finalizeConnections(); } } @@ -655,10 +661,9 @@ extern "C" { // necessary for getting instance out of shared lib -PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *, void * _data ) +PLUGIN_EXPORT Plugin * lmms_plugin_main(Model * m, void *) { - - return new ZynAddSubFxInstrument( static_cast( _data ) ); + return new ZynAddSubFxInstrument(static_cast(m)); } diff --git a/plugins/zynaddsubfx/ZynAddSubFx.h b/plugins/zynaddsubfx/ZynAddSubFx.h index e8974d149..6f5bc754d 100644 --- a/plugins/zynaddsubfx/ZynAddSubFx.h +++ b/plugins/zynaddsubfx/ZynAddSubFx.h @@ -132,7 +132,7 @@ signals: -class ZynAddSubFxView : public InstrumentView +class ZynAddSubFxView : public InstrumentViewFixedSize { Q_OBJECT public: diff --git a/plugins/zynaddsubfx/zynaddsubfx b/plugins/zynaddsubfx/zynaddsubfx index 9cd29e224..ccac06336 160000 --- a/plugins/zynaddsubfx/zynaddsubfx +++ b/plugins/zynaddsubfx/zynaddsubfx @@ -1 +1 @@ -Subproject commit 9cd29e224320c40b00343b7e49e586ef25733a71 +Subproject commit ccac06336b363b9afe7ff4aea02bfa2d48187e1a diff --git a/src/3rdparty/CMakeLists.txt b/src/3rdparty/CMakeLists.txt index 7bc0a8790..473e7702f 100644 --- a/src/3rdparty/CMakeLists.txt +++ b/src/3rdparty/CMakeLists.txt @@ -1,7 +1,9 @@ set(CMAKE_C_FLAGS "") set(CMAKE_CXX_FLAGS "") +set(CMAKE_C_FLAGS_DEBUG "") +set(CMAKE_CXX_FLAGS_DEBUG "") -IF(LMMS_BUILD_LINUX) +IF(LMMS_BUILD_LINUX AND WANT_VST) set(BUILD_SHARED_LIBS OFF) add_subdirectory(qt5-x11embed) ENDIF() diff --git a/src/3rdparty/mingw-std-threads b/src/3rdparty/mingw-std-threads new file mode 160000 index 000000000..10665829d --- /dev/null +++ b/src/3rdparty/mingw-std-threads @@ -0,0 +1 @@ +Subproject commit 10665829daaedc28629e5e9b014fe498c20d73f2 diff --git a/src/3rdparty/rpmalloc/rpmalloc b/src/3rdparty/rpmalloc/rpmalloc index 36b1942fb..b5bdc1805 160000 --- a/src/3rdparty/rpmalloc/rpmalloc +++ b/src/3rdparty/rpmalloc/rpmalloc @@ -1 +1 @@ -Subproject commit 36b1942fbc309b139e56a03166ba19a87f28f26c +Subproject commit b5bdc18051bb74a22f0bde4bcc90b01cf590b496 diff --git a/src/3rdparty/weakjack/CMakeLists.txt b/src/3rdparty/weakjack/CMakeLists.txt index b9f24e331..7600c3915 100644 --- a/src/3rdparty/weakjack/CMakeLists.txt +++ b/src/3rdparty/weakjack/CMakeLists.txt @@ -7,6 +7,6 @@ IF(LMMS_HAVE_WEAKJACK) # Library stub for AppImages running on systems without jack ADD_LIBRARY(weakjack MODULE weakjack/weak_libjack.c weakjack/weak_libjack.h) - TARGET_INCLUDE_DIRECTORIES(weakjack PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/weakjack) + TARGET_INCLUDE_DIRECTORIES(weakjack PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/weakjack ${JACK_INCLUDE_DIRS}) INSTALL(TARGETS weakjack LIBRARY DESTINATION "${PLUGIN_DIR}/optional") ENDIF() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ff0ca8a8e..ed0deefd1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -45,18 +45,19 @@ INCLUDE(GenQrc) ADD_GEN_QRC(LMMS_RCC_OUT lmms.qrc "${CMAKE_SOURCE_DIR}/doc/AUTHORS" "${CMAKE_SOURCE_DIR}/LICENSE.txt" - "${CMAKE_BINARY_DIR}/CONTRIBUTORS" + "${CONTRIBUTORS}" ) # Paths relative to lmms executable FILE(RELATIVE_PATH LIB_DIR_RELATIVE "/${BIN_DIR}" "/${LIB_DIR}") FILE(RELATIVE_PATH PLUGIN_DIR_RELATIVE "/${BIN_DIR}" "/${PLUGIN_DIR}") -ADD_DEFINITIONS(-D'LIB_DIR="${LIB_DIR_RELATIVE}/"' -D'PLUGIN_DIR="${PLUGIN_DIR_RELATIVE}/"' ${PULSEAUDIO_DEFINITIONS} ${PORTAUDIO_DEFINITIONS}) +ADD_DEFINITIONS(-DLIB_DIR="${LIB_DIR_RELATIVE}" -DPLUGIN_DIR="${PLUGIN_DIR_RELATIVE}" ${PULSEAUDIO_DEFINITIONS} ${PORTAUDIO_DEFINITIONS}) INCLUDE_DIRECTORIES( ${JACK_INCLUDE_DIRS} ${SAMPLERATE_INCLUDE_DIRS} ${SNDFILE_INCLUDE_DIRS} ${SNDIO_INCLUDE_DIRS} + ${FFTW3F_INCLUDE_DIRS} ) IF(NOT ("${SDL2_INCLUDE_DIR}" STREQUAL "")) @@ -101,11 +102,36 @@ ADD_LIBRARY(lmmsobjs OBJECT ${LMMS_UI_OUT} ${LMMS_RCC_OUT} ) + +GENERATE_EXPORT_HEADER(lmmsobjs + BASE_NAME lmms +) + ADD_EXECUTABLE(lmms core/main.cpp $ "${WINRC}" ) +TARGET_INCLUDE_DIRECTORIES(lmms + PUBLIC ${CMAKE_CURRENT_BINARY_DIR} +) + +# CMake doesn't define target_EXPORTS for OBJECT libraries. +# See the documentation of DEFINE_SYMBOL for details. +# Also add LMMS_STATIC_DEFINE for targets linking against it. +TARGET_COMPILE_DEFINITIONS(lmmsobjs + PRIVATE -Dlmmsobjs_EXPORTS + INTERFACE -DLMMS_STATIC_DEFINE +) +TARGET_COMPILE_DEFINITIONS(lmms + PRIVATE $ +) + +# Set Visual Studio startup project to lmms +# https://stackoverflow.com/a/37994396/8166701 +IF(NOT CMAKE_VERSION VERSION_LESS 3.6) + SET_PROPERTY(DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT lmms) +ENDIF() SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${LMMS_RCC_OUT} ${LMMS_UI_OUT} lmmsconfig.h lmms.1.gz") @@ -133,7 +159,7 @@ SET(LMMS_REQUIRED_LIBS ${LMMS_REQUIRED_LIBS} ${SDL2_LIBRARY} ${PORTAUDIO_LIBRARIES} ${SOUNDIO_LIBRARY} - ${SNDIO_LIBRARY} + ${SNDIO_LIBRARIES} ${PULSEAUDIO_LIBRARIES} ${JACK_LIBRARIES} ${OGGVORBIS_LIBRARIES} @@ -160,96 +186,30 @@ FOREACH(LIB ${LMMS_REQUIRED_LIBS}) ENDIF() ENDFOREACH() - -# Required libs for debug msys builds -IF(LMMS_BUILD_MSYS AND CMAKE_BUILD_TYPE STREQUAL "Debug") - TARGET_LINK_LIBRARIES(lmms QtCore4 QtGui4 QtXml4) -ENDIF() - -# Install IF(LMMS_BUILD_WIN32) SET_TARGET_PROPERTIES(lmms PROPERTIES - LINK_FLAGS "${LINK_FLAGS} -mwindows" ENABLE_EXPORTS ON ) - 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 .) + # 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(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) +ELSE() 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) + 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() -ENDIF(LMMS_BUILD_WIN32) +INSTALL(TARGETS lmms RUNTIME DESTINATION "${BIN_DIR}") diff --git a/src/core/AutomatableModel.cpp b/src/core/AutomatableModel.cpp index 425ec59ef..6055598f7 100644 --- a/src/core/AutomatableModel.cpp +++ b/src/core/AutomatableModel.cpp @@ -28,8 +28,10 @@ #include "AutomationPattern.h" #include "ControllerConnection.h" +#include "LocaleHelper.h" #include "Mixer.h" #include "ProjectJournal.h" +#include "Song.h" long AutomatableModel::s_periodCounter = 0; @@ -88,26 +90,57 @@ bool AutomatableModel::isAutomated() const } + +bool AutomatableModel::mustQuoteName(const QString& name) +{ + QRegExp reg("^[A-Za-z0-9._-]+$"); + return !reg.exactMatch(name); +} + void AutomatableModel::saveSettings( QDomDocument& doc, QDomElement& element, const QString& name ) { + bool mustQuote = mustQuoteName(name); + if( isAutomated() || m_scaleType != Linear ) { // automation needs tuple of data (name, id, value) // scale type also needs an extra value // => it must be appended as a node - QDomElement me = doc.createElement( name ); + + QDomElement me = doc.createElement( mustQuote ? QString("automatablemodel") : name ); me.setAttribute( "id", ProjectJournal::idToSave( id() ) ); me.setAttribute( "value", m_value ); me.setAttribute( "scale_type", m_scaleType == Logarithmic ? "log" : "linear" ); + if(mustQuote) { + me.setAttribute( "nodename", name ); + } element.appendChild( me ); } else { - // non automation, linear scale (default), can be saved as attribute - element.setAttribute( name, m_value ); + if(mustQuote) + { + QDomElement me = doc.createElement( "automatablemodel" ); + me.setAttribute( "nodename", name ); + me.setAttribute( "value", m_value ); + element.appendChild( me ); + } + else + { + // non automation, linear scale (default), can be saved as attribute + element.setAttribute( name, m_value ); + } } - if( m_controllerConnection ) + // Skip saving MIDI connections if we're saving project and + // the discardMIDIConnections option is true. + auto controllerType = m_controllerConnection + ? m_controllerConnection->getController()->type() + : Controller::DummyController; + bool skipMidiController = Engine::getSong()->isSavingProject() + && Engine::getSong()->getSaveOptions().discardMIDIConnections.value(); + if (m_controllerConnection && controllerType != Controller::DummyController + && !(skipMidiController && controllerType == Controller::MidiController)) { QDomElement controllerElement; @@ -123,7 +156,13 @@ void AutomatableModel::saveSettings( QDomDocument& doc, QDomElement& element, co element.appendChild( controllerElement ); } - QDomElement element = doc.createElement( name ); + bool mustQuote = mustQuoteName(name); + QString elementName = mustQuote ? "controllerconnection" + : name; + + QDomElement element = doc.createElement( elementName ); + if(mustQuote) + element.setAttribute( "nodename", name ); m_controllerConnection->saveSettings( doc, element ); controllerElement.appendChild( element ); @@ -162,6 +201,17 @@ void AutomatableModel::loadSettings( const QDomElement& element, const QString& if( connectionNode.isElement() ) { QDomNode thisConnection = connectionNode.toElement().namedItem( name ); + if( !thisConnection.isElement() ) + { + thisConnection = connectionNode.toElement().namedItem( "controllerconnection" ); + QDomElement tcElement = thisConnection.toElement(); + // sanity check + if( tcElement.isNull() || tcElement.attribute( "nodename" ) != name ) + { + // no, that wasn't it, act as if we never found one + thisConnection.clear(); + } + } if( thisConnection.isElement() ) { setControllerConnection( new ControllerConnection( (Controller*)NULL ) ); @@ -175,22 +225,48 @@ void AutomatableModel::loadSettings( const QDomElement& element, const QString& // // // element => there is automation data, or scaletype information - node = element.namedItem( name ); + + node = element.namedItem( name ); // maybe we have luck? + + // either: no node with name "name" found + // => look for nodes with attribute name="nodename" + // or: element with namedItem() "name" was found, but it's real nodename + // is given as attribute and does not match + // => look for the right node + if(node.isNull() || + ( node.isElement() && + node.toElement().hasAttribute("nodename") && + node.toElement().attribute("nodename") != name)) + { + for(QDomElement othernode = element.firstChildElement(); + !othernode.isNull(); + othernode = othernode.nextSiblingElement()) + { + if((!othernode.hasAttribute("nodename") && + othernode.nodeName() == name) || + othernode.attribute("nodename") == name) + { + node = othernode; + break; + } + } + } if( node.isElement() ) { - changeID( node.toElement().attribute( "id" ).toInt() ); - setValue( node.toElement().attribute( "value" ).toFloat() ); - if( node.toElement().hasAttribute( "scale_type" ) ) + QDomElement nodeElement = node.toElement(); + changeID( nodeElement.attribute( "id" ).toInt() ); + setValue( LocaleHelper::toFloat( nodeElement.attribute( "value" ) ) ); + if( nodeElement.hasAttribute( "scale_type" ) ) + { + if( nodeElement.attribute( "scale_type" ) == "linear" ) { - if( node.toElement().attribute( "scale_type" ) == "linear" ) - { - setScaleType( Linear ); - } - else if( node.toElement().attribute( "scale_type" ) == "log" ) - { - setScaleType( Logarithmic ); - } + setScaleType( Linear ); } + else if( nodeElement.attribute( "scale_type" ) == "log" ) + { + setScaleType( Logarithmic ); + } + } } else { @@ -200,7 +276,7 @@ void AutomatableModel::loadSettings( const QDomElement& element, const QString& if( element.hasAttribute( name ) ) // attribute => read the element's value from the attribute list { - setInitValue( element.attribute( name ).toFloat() ); + setInitValue( LocaleHelper::toFloat( element.attribute( name ) ) ); } else { @@ -363,7 +439,7 @@ void AutomatableModel::setStep( const float step ) float AutomatableModel::fittedValue( float value ) const { - value = tLimit( value, m_minValue, m_maxValue ); + value = qBound( m_minValue, value, m_maxValue ); if( m_step != 0 && m_hasStrictStepSize ) { @@ -398,7 +474,8 @@ void AutomatableModel::linkModel( AutomatableModel* model ) if( !model->hasLinkedModels() ) { - QObject::connect( this, SIGNAL( dataChanged() ), model, SIGNAL( dataChanged() ) ); + QObject::connect( this, SIGNAL( dataChanged() ), + model, SIGNAL( dataChanged() ), Qt::DirectConnection ); } } } @@ -408,7 +485,7 @@ void AutomatableModel::linkModel( AutomatableModel* model ) void AutomatableModel::unlinkModel( AutomatableModel* model ) { - AutoModelVector::Iterator it = qFind( m_linkedModels.begin(), m_linkedModels.end(), model ); + AutoModelVector::Iterator it = std::find( m_linkedModels.begin(), m_linkedModels.end(), model ); if( it != m_linkedModels.end() ) { m_linkedModels.erase( it ); @@ -454,7 +531,8 @@ void AutomatableModel::setControllerConnection( ControllerConnection* c ) m_controllerConnection = c; if( c ) { - QObject::connect( m_controllerConnection, SIGNAL( valueChanged() ), this, SIGNAL( dataChanged() ) ); + QObject::connect( m_controllerConnection, SIGNAL( valueChanged() ), + this, SIGNAL( dataChanged() ), Qt::DirectConnection ); QObject::connect( m_controllerConnection, SIGNAL( destroyed() ), this, SLOT( unlinkControllerConnection() ) ); m_valueChanged = true; emit dataChanged(); diff --git a/src/core/AutomationPattern.cpp b/src/core/AutomationPattern.cpp index 9345ad566..b38c704ef 100644 --- a/src/core/AutomationPattern.cpp +++ b/src/core/AutomationPattern.cpp @@ -28,6 +28,7 @@ #include "AutomationPatternView.h" #include "AutomationTrack.h" +#include "LocaleHelper.h" #include "Note.h" #include "ProjectJournal.h" #include "BBTrackContainer.h" @@ -144,11 +145,11 @@ void AutomationPattern::setProgressionType( void AutomationPattern::setTension( QString _new_tension ) { bool ok; - float nt = _new_tension.toFloat( & ok ); + float nt = LocaleHelper::toFloat(_new_tension, & ok); if( ok && nt > -0.01 && nt < 1.01 ) { - m_tension = _new_tension.toFloat(); + m_tension = nt; } } @@ -179,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 ); } @@ -585,7 +586,7 @@ void AutomationPattern::loadSettings( const QDomElement & _this ) if( element.tagName() == "time" ) { m_timeMap[element.attribute( "pos" ).toInt()] - = element.attribute( "value" ).toFloat(); + = LocaleHelper::toFloat(element.attribute("value")); } else if( element.tagName() == "object" ) { @@ -619,12 +620,7 @@ const QString AutomationPattern::name() const { return m_objects.first()->fullDisplayName(); } - return tr( "Drag a control while pressing <%1>" ).arg( - #ifdef LMMS_BUILD_APPLE - "⌘"); - #else - "Ctrl"); - #endif + return tr( "Drag a control while pressing <%1>" ).arg(UI_CTRL_KEY); } @@ -776,6 +772,26 @@ void AutomationPattern::resolveAllIDs() { a->addObject( dynamic_cast( o ), false ); } + else + { + // FIXME: Remove this block once the automation system gets fixed + // This is a temporary fix for https://github.com/LMMS/lmms/issues/3781 + o = Engine::projectJournal()->journallingObject(ProjectJournal::idFromSave(*k)); + if( o && dynamic_cast( o ) ) + { + a->addObject( dynamic_cast( o ), false ); + } + else + { + // FIXME: Remove this block once the automation system gets fixed + // This is a temporary fix for https://github.com/LMMS/lmms/issues/4781 + o = Engine::projectJournal()->journallingObject(ProjectJournal::idToSave(*k)); + if( o && dynamic_cast( o ) ) + { + a->addObject( dynamic_cast( o ), false ); + } + } + } } a->m_idsToResolve.clear(); a->dataChanged(); diff --git a/src/core/BBTrackContainer.cpp b/src/core/BBTrackContainer.cpp index e9af1f621..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,18 +90,21 @@ 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( TrackList::const_iterator it = tl.begin(); it != tl.end(); ++it ) + for (Track* t : tl) { - max_length = qMax( max_length, - ( *it )->getTCO( _bb )->length() ); + // Don't create TCOs here if not exist + if (_bb < t->numOfTCOs()) + { + max_length = qMax(max_length, t->getTCO( _bb )->length()); + } } - return max_length.nextFullTact(); + return max_length.nextFullBar(); } @@ -121,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() ) { @@ -148,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(); @@ -244,16 +247,13 @@ AutomatedValueMap BBTrackContainer::automatedValuesAt(MidiTime time, int tcoNum) Q_ASSERT(tcoNum >= 0); Q_ASSERT(time.getTicks() >= 0); - auto length_tacts = lengthOfBB(tcoNum); - auto length_ticks = length_tacts * MidiTime::ticksPerTact(); - if (time > length_ticks) { + auto length_bars = lengthOfBB(tcoNum); + auto length_ticks = length_bars * MidiTime::ticksPerBar(); + if (time > length_ticks) + { time = length_ticks; } - return TrackContainer::automatedValuesAt(time + (MidiTime::ticksPerTact() * tcoNum), tcoNum); + return TrackContainer::automatedValuesAt(time + (MidiTime::ticksPerBar() * tcoNum), tcoNum); } - - - - diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index b06bc28d9..4503046ef 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -46,6 +46,7 @@ set(LMMS_SRCS core/MixerWorkerThread.cpp core/MixHelpers.cpp core/Model.cpp + core/ModelVisitor.cpp core/Note.cpp core/NotePlayHandle.cpp core/Oscillator.cpp @@ -54,6 +55,7 @@ set(LMMS_SRCS core/Piano.cpp core/PlayHandle.cpp core/Plugin.cpp + core/PluginIssue.cpp core/PluginFactory.cpp core/PresetPreviewPlayHandle.cpp core/ProjectJournal.cpp @@ -73,6 +75,7 @@ set(LMMS_SRCS core/TrackContainer.cpp core/ValueBuffer.cpp core/VstSyncController.cpp + core/StepRecorder.cpp core/audio/AudioAlsa.cpp core/audio/AudioDevice.cpp diff --git a/src/core/ConfigManager.cpp b/src/core/ConfigManager.cpp index f52e10ac7..b8e8cd4ae 100644 --- a/src/core/ConfigManager.cpp +++ b/src/core/ConfigManager.cpp @@ -22,15 +22,12 @@ * */ + #include #include #include #include -#if QT_VERSION >= 0x050000 #include -#else -#include -#endif #include #include "ConfigManager.h" @@ -40,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 + '/'; } @@ -54,18 +52,14 @@ ConfigManager * ConfigManager::s_instanceOfMe = NULL; ConfigManager::ConfigManager() : - m_lmmsRcFile( QDir::home().absolutePath() +"/.lmmsrc.xml" ), - #if QT_VERSION >= 0x050000 - m_workingDir( QStandardPaths::writableLocation( QStandardPaths::DocumentsLocation ) + "/lmms/"), - #else - m_workingDir( QDesktopServices::storageLocation( QDesktopServices::DocumentsLocation ) + "/lmms/"), - #endif - 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() ) @@ -133,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 @@ -157,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"); } } @@ -167,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 @@ -210,13 +204,8 @@ QStringList ConfigManager::availabeVstEmbedMethods() methods.append("win32"); #endif #ifdef LMMS_BUILD_LINUX -#if QT_VERSION >= 0x050000 if (static_cast(QApplication::instance())-> platformName() == "xcb") -#else - if (qgetenv("QT_QPA_PLATFORM").isNull() - || qgetenv("QT_QPA_PLATFORM") == "xcb") -#endif { methods.append("xembed"); } @@ -234,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(); } } @@ -342,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 ; } } } @@ -363,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; @@ -415,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(); @@ -439,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(); } @@ -481,69 +478,70 @@ 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(); } - + // Plugins are searched recursively, blacklist problematic locations if( m_vstDir.isEmpty() || m_vstDir == QDir::separator() || m_vstDir == "/" || + m_vstDir == ensureTrailingSlash( QDir::homePath() ) || !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/"; @@ -569,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(); } @@ -584,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/ControllerConnection.cpp b/src/core/ControllerConnection.cpp index 280ed709c..e08f15b63 100644 --- a/src/core/ControllerConnection.cpp +++ b/src/core/ControllerConnection.cpp @@ -117,7 +117,7 @@ void ControllerConnection::setController( Controller * _controller ) { _controller->addConnection( this ); QObject::connect( _controller, SIGNAL( valueChanged() ), - this, SIGNAL( valueChanged() ) ); + this, SIGNAL( valueChanged() ), Qt::DirectConnection ); } m_ownsController = @@ -162,6 +162,11 @@ void ControllerConnection::finalizeConnections() c->setController( Engine::getSong()-> controllers().at( c->m_controllerId ) ); } + else if (c->getController()->type() == Controller::DummyController) + { + delete c; + --i; + } } } @@ -199,16 +204,24 @@ void ControllerConnection::loadSettings( const QDomElement & _this ) } else { - if( _this.attribute( "id" ).toInt() >= 0 ) - { - m_controllerId = _this.attribute( "id" ).toInt(); - } - else + m_controllerId = _this.attribute( "id", "-1" ).toInt(); + if( m_controllerId < 0 ) { qWarning( "controller index invalid\n" ); m_controllerId = -1; } - m_controller = Controller::create( Controller::DummyController, NULL ); + + if (!Engine::getSong()->isLoadingProject() + && m_controllerId != -1 + && m_controllerId < Engine::getSong()->controllers().size()) + { + setController( Engine::getSong()-> + controllers().at( m_controllerId ) ); + } + else + { + m_controller = Controller::create( Controller::DummyController, NULL ); + } } } diff --git a/src/core/DataFile.cpp b/src/core/DataFile.cpp index bf2a43e6e..129c9738b 100644 --- a/src/core/DataFile.cpp +++ b/src/core/DataFile.cpp @@ -38,6 +38,7 @@ #include "Effect.h" #include "embed.h" #include "GuiApplication.h" +#include "LocaleHelper.h" #include "PluginFactory.h" #include "ProjectVersion.h" #include "SongEditor.h" @@ -65,37 +66,6 @@ DataFile::typeDescStruct -DataFile::LocaleHelper::LocaleHelper( Mode mode ) -{ - switch( mode ) - { - case ModeLoad: - // set a locale for which QString::fromFloat() returns valid values if - // floating point separator is a comma - otherwise we would fail to load - // older projects made by people from various countries due to their - // locale settings - QLocale::setDefault( QLocale::German ); - break; - - case ModeSave: - // set default locale to C so that floating point decimals are rendered to - // strings with periods as decimal point instead of commas in some countries - QLocale::setDefault( QLocale::C ); - - default: break; - } -} - - - -DataFile::LocaleHelper::~LocaleHelper() -{ - // revert to original locale - QLocale::setDefault( QLocale::system() ); -} - - - DataFile::DataFile( Type type ) : QDomDocument( "lmms-project" ), @@ -416,8 +386,8 @@ void DataFile::upgrade_0_2_1_20070501() QDomElement el = list.item( i ).toElement(); if( el.attribute( "vol" ) != "" ) { - el.setAttribute( "vol", el.attribute( - "vol" ).toFloat() * 100.0f ); + el.setAttribute( "vol", LocaleHelper::toFloat( + el.attribute( "vol" ) ) * 100.0f ); } else { @@ -543,7 +513,7 @@ void DataFile::upgrade_0_2_1_20070508() QDomElement el = list.item( i ).toElement(); if( el.hasAttribute( "vol" ) ) { - float value = el.attribute( "vol" ).toFloat(); + float value = LocaleHelper::toFloat( el.attribute( "vol" ) ); value = roundf( value * 0.585786438f ); el.setAttribute( "vol", value ); } diff --git a/src/core/DrumSynth.cpp b/src/core/DrumSynth.cpp index 3379f1aa7..c41de1fd4 100644 --- a/src/core/DrumSynth.cpp +++ b/src/core/DrumSynth.cpp @@ -26,11 +26,13 @@ #include "DrumSynth.h" -#include +#include #include #include //sin(), exp(), etc. +#include + #ifdef LMMS_BUILD_WIN32 #define powf pow #endif @@ -117,12 +119,15 @@ void DrumSynth::UpdateEnv(int e, long t) } -void DrumSynth::GetEnv(int env, const char *sec, const char *key, const char *ini) +void DrumSynth::GetEnv(int env, const char *sec, const char *key, QString ini) { char en[256], s[8]; int i=0, o=0, ep=0; GetPrivateProfileString(sec, key, "0,0 100,0", en, sizeof(en), ini); - en[255]=0; //be safe! + + //be safe! + en[255]=0; + s[0]=0; while(en[i]!=0) { @@ -167,9 +172,9 @@ float DrumSynth::waveform(float ph, int form) } -int DrumSynth::GetPrivateProfileString(const char *sec, const char *key, const char *def, char *buffer, int size, const char *file) +int DrumSynth::GetPrivateProfileString(const char *sec, const char *key, const char *def, char *buffer, int size, QString file) { - ifstream is; + stringstream is; bool inSection = false; char *line; char *k, *b; @@ -177,7 +182,12 @@ int DrumSynth::GetPrivateProfileString(const char *sec, const char *key, const c line = (char*)malloc(200); - is.open (file, ifstream::in); + // Use QFile to handle unicode file name on Windows + // Previously we used ifstream directly + QFile f(file); + f.open(QIODevice::ReadOnly); + QByteArray dat = f.readAll().constData(); + is.str(string(dat.constData(), dat.size())); while (is.good()) { if (!inSection) { @@ -223,13 +233,12 @@ int DrumSynth::GetPrivateProfileString(const char *sec, const char *key, const c strncpy(buffer, def, size); } - is.close(); free(line); return len; } -int DrumSynth::GetPrivateProfileInt(const char *sec, const char *key, int def, const char *file) +int DrumSynth::GetPrivateProfileInt(const char *sec, const char *key, int def, QString file) { char tmp[16]; int i=0; @@ -240,7 +249,7 @@ int DrumSynth::GetPrivateProfileInt(const char *sec, const char *key, int def, c return i; } -float DrumSynth::GetPrivateProfileFloat(const char *sec, const char *key, float def, const char *file) +float DrumSynth::GetPrivateProfileFloat(const char *sec, const char *key, float def, QString file) { char tmp[16]; float f=0.f; @@ -257,7 +266,7 @@ float DrumSynth::GetPrivateProfileFloat(const char *sec, const char *key, float // an associative array or something once we have a datastructure to load in to. // llama -int DrumSynth::GetDSFileSamples(const char *dsfile, int16_t *&wave, int channels, sample_rate_t Fs) +int DrumSynth::GetDSFileSamples(QString dsfile, int16_t *&wave, int channels, sample_rate_t Fs) { //input file char sec[32]; diff --git a/src/core/Effect.cpp b/src/core/Effect.cpp index 8cdcc9c60..c84297753 100644 --- a/src/core/Effect.cpp +++ b/src/core/Effect.cpp @@ -36,9 +36,8 @@ Effect::Effect( const Plugin::Descriptor * _desc, Model * _parent, const Descriptor::SubPluginFeatures::Key * _key ) : - Plugin( _desc, _parent ), + Plugin( _desc, _parent, _key ), m_parent( NULL ), - m_key( _key ? *_key : Descriptor::SubPluginFeatures::Key() ), m_processors( 1 ), m_okay( true ), m_noRun( false ), @@ -117,7 +116,7 @@ Effect * Effect::instantiate( const QString& pluginName, Model * _parent, Descriptor::SubPluginFeatures::Key * _key ) { - Plugin * p = Plugin::instantiate( pluginName, _parent, _key ); + Plugin * p = Plugin::instantiateWithKey( pluginName, _parent, _key ); // check whether instantiated plugin is an effect if( dynamic_cast( p ) != NULL ) { diff --git a/src/core/EffectChain.cpp b/src/core/EffectChain.cpp index 886899c04..21b85917b 100644 --- a/src/core/EffectChain.cpp +++ b/src/core/EffectChain.cpp @@ -53,7 +53,7 @@ EffectChain::~EffectChain() void EffectChain::saveSettings( QDomDocument & _doc, QDomElement & _this ) { - _this.setAttribute( "enabled", m_enabledModel.value() ); + m_enabledModel.saveSettings( _doc, _this, "enabled" ); _this.setAttribute( "numofeffects", m_effects.count() ); for( Effect* effect : m_effects) @@ -80,7 +80,7 @@ void EffectChain::loadSettings( const QDomElement & _this ) // TODO This method should probably also lock the mixer - m_enabledModel.setValue( _this.attribute( "enabled" ).toInt() ); + m_enabledModel.loadSettings( _this, "enabled" ); const int plugin_cnt = _this.attribute( "numofeffects" ).toInt(); @@ -137,7 +137,7 @@ void EffectChain::removeEffect( Effect * _effect ) { Engine::mixer()->requestChangeInModel(); - Effect ** found = qFind( m_effects.begin(), m_effects.end(), _effect ); + Effect ** found = std::find( m_effects.begin(), m_effects.end(), _effect ); if( found == m_effects.end() ) { Engine::mixer()->doneChangeInModel(); diff --git a/src/core/Engine.cpp b/src/core/Engine.cpp index a53abbe5d..ce82310fa 100644 --- a/src/core/Engine.cpp +++ b/src/core/Engine.cpp @@ -29,6 +29,7 @@ #include "FxMixer.h" #include "Ladspa2LMMS.h" #include "Mixer.h" +#include "Plugin.h" #include "PresetPreviewPlayHandle.h" #include "ProjectJournal.h" #include "Song.h" @@ -41,6 +42,7 @@ BBTrackContainer * LmmsCore::s_bbTrackContainer = NULL; Song * LmmsCore::s_song = NULL; ProjectJournal * LmmsCore::s_projectJournal = NULL; Ladspa2LMMS * LmmsCore::s_ladspaManager = NULL; +void* LmmsCore::s_dndPluginKey = nullptr; DummyTrackContainer * LmmsCore::s_dummyTC = NULL; @@ -103,13 +105,39 @@ void LmmsCore::destroy() delete ConfigManager::inst(); } +float LmmsCore::framesPerTick(sample_rate_t sampleRate) +{ + return sampleRate * 60.0f * 4 / + DefaultTicksPerBar / s_song->getTempo(); +} + void LmmsCore::updateFramesPerTick() { s_framesPerTick = s_mixer->processingSampleRate() * 60.0f * 4 / - DefaultTicksPerTact / s_song->getTempo(); + DefaultTicksPerBar / s_song->getTempo(); } + + + +void LmmsCore::setDndPluginKey(void *newKey) +{ + Q_ASSERT(static_cast(newKey)); + s_dndPluginKey = newKey; +} + + + + +void *LmmsCore::pickDndPluginKey() +{ + return s_dndPluginKey; +} + + + + LmmsCore * LmmsCore::s_instanceOfMe = NULL; diff --git a/src/core/EnvelopeAndLfoParameters.cpp b/src/core/EnvelopeAndLfoParameters.cpp index 9001cd796..27a73b2c1 100644 --- a/src/core/EnvelopeAndLfoParameters.cpp +++ b/src/core/EnvelopeAndLfoParameters.cpp @@ -131,32 +131,32 @@ EnvelopeAndLfoParameters::EnvelopeAndLfoParameters( instances()->add( this ); connect( &m_predelayModel, SIGNAL( dataChanged() ), - this, SLOT( updateSampleVars() ) ); + this, SLOT( updateSampleVars() ), Qt::DirectConnection ); connect( &m_attackModel, SIGNAL( dataChanged() ), - this, SLOT( updateSampleVars() ) ); + this, SLOT( updateSampleVars() ), Qt::DirectConnection ); connect( &m_holdModel, SIGNAL( dataChanged() ), - this, SLOT( updateSampleVars() ) ); + this, SLOT( updateSampleVars() ), Qt::DirectConnection ); connect( &m_decayModel, SIGNAL( dataChanged() ), - this, SLOT( updateSampleVars() ) ); + this, SLOT( updateSampleVars() ), Qt::DirectConnection ); connect( &m_sustainModel, SIGNAL( dataChanged() ), - this, SLOT( updateSampleVars() ) ); + this, SLOT( updateSampleVars() ), Qt::DirectConnection ); connect( &m_releaseModel, SIGNAL( dataChanged() ), - this, SLOT( updateSampleVars() ) ); + this, SLOT( updateSampleVars() ), Qt::DirectConnection ); connect( &m_amountModel, SIGNAL( dataChanged() ), - this, SLOT( updateSampleVars() ) ); + this, SLOT( updateSampleVars() ), Qt::DirectConnection ); connect( &m_lfoPredelayModel, SIGNAL( dataChanged() ), - this, SLOT( updateSampleVars() ) ); + this, SLOT( updateSampleVars() ), Qt::DirectConnection ); connect( &m_lfoAttackModel, SIGNAL( dataChanged() ), - this, SLOT( updateSampleVars() ) ); + this, SLOT( updateSampleVars() ), Qt::DirectConnection ); connect( &m_lfoSpeedModel, SIGNAL( dataChanged() ), - this, SLOT( updateSampleVars() ) ); + this, SLOT( updateSampleVars() ), Qt::DirectConnection ); connect( &m_lfoAmountModel, SIGNAL( dataChanged() ), - this, SLOT( updateSampleVars() ) ); + this, SLOT( updateSampleVars() ), Qt::DirectConnection ); connect( &m_lfoWaveModel, SIGNAL( dataChanged() ), - this, SLOT( updateSampleVars() ) ); + this, SLOT( updateSampleVars() ), Qt::DirectConnection ); connect( &m_x100Model, SIGNAL( dataChanged() ), - this, SLOT( updateSampleVars() ) ); + this, SLOT( updateSampleVars() ), Qt::DirectConnection ); connect( Engine::mixer(), SIGNAL( sampleRateChanged() ), this, SLOT( updateSampleVars() ) ); diff --git a/src/core/FxMixer.cpp b/src/core/FxMixer.cpp index 51e66939a..f04435e05 100644 --- a/src/core/FxMixer.cpp +++ b/src/core/FxMixer.cpp @@ -32,6 +32,7 @@ #include "Song.h" #include "InstrumentTrack.h" +#include "SampleTrack.h" #include "BBTrackContainer.h" FxRoute::FxRoute( FxChannel * from, FxChannel * to, float amount ) : @@ -170,11 +171,9 @@ void FxChannel::doProcessing() m_stillRunning = m_fxChain.processAudioBuffer( m_buffer, fpp, m_hasInput ); - float peakLeft = 0.; - float peakRight = 0.; - Engine::mixer()->getPeakValues( m_buffer, fpp, peakLeft, peakRight ); - m_peakLeft = qMax( m_peakLeft, peakLeft * v ); - m_peakRight = qMax( m_peakRight, peakRight * v ); + Mixer::StereoSample peakSamples = Engine::mixer()->getPeakValues(m_buffer, fpp); + m_peakLeft = qMax( m_peakLeft, peakSamples.left * v ); + m_peakRight = qMax( m_peakRight, peakSamples.right * v ); } else { @@ -307,6 +306,22 @@ void FxMixer::deleteChannel( int index ) inst->effectChannelModel()->setValue(val-1); } } + else if( t->type() == Track::SampleTrack ) + { + SampleTrack* strk = dynamic_cast( t ); + int val = strk->effectChannelModel()->value(0); + if( val == index ) + { + // we are deleting this track's fx send + // send to master + strk->effectChannelModel()->setValue(0); + } + else if( val > index ) + { + // subtract 1 to make up for the missing channel + strk->effectChannelModel()->setValue(val-1); + } + } } FxChannel * ch = m_fxChannels[index]; @@ -321,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; @@ -358,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(); @@ -381,6 +405,19 @@ void FxMixer::moveChannelLeft( int index ) inst->effectChannelModel()->setValue(a); } } + else if( trackList[i]->type() == Track::SampleTrack ) + { + SampleTrack * strk = (SampleTrack *) trackList[i]; + int val = strk->effectChannelModel()->value(0); + if( val == a ) + { + strk->effectChannelModel()->setValue(b); + } + else if( val == b ) + { + strk->effectChannelModel()->setValue(a); + } + } } } @@ -782,4 +819,3 @@ void FxMixer::validateChannelName( int index, int oldIndex ) m_fxChannels[index]->m_name = tr( "FX %1" ).arg( index ); } } - diff --git a/src/core/Instrument.cpp b/src/core/Instrument.cpp index 534bb783a..ba608da14 100644 --- a/src/core/Instrument.cpp +++ b/src/core/Instrument.cpp @@ -27,9 +27,10 @@ #include "DummyInstrument.h" -Instrument::Instrument( InstrumentTrack * _instrument_track, - const Descriptor * _descriptor ) : - Plugin( _descriptor, NULL/* _instrument_track*/ ), +Instrument::Instrument(InstrumentTrack * _instrument_track, + const Descriptor * _descriptor, + const Descriptor::SubPluginFeatures::Key *key) : + Plugin(_descriptor, NULL/* _instrument_track*/, key), m_instrumentTrack( _instrument_track ) { } @@ -56,19 +57,15 @@ f_cnt_t Instrument::beatLen( NotePlayHandle * ) const -Instrument * Instrument::instantiate( const QString & _plugin_name, - InstrumentTrack * _instrument_track ) +Instrument *Instrument::instantiate(const QString &_plugin_name, + InstrumentTrack *_instrument_track, const Descriptor::SubPluginFeatures::Key *key, bool keyFromDnd) { - Plugin * p = Plugin::instantiate( _plugin_name, _instrument_track, - _instrument_track ); - // check whether instantiated plugin is an instrument - if( dynamic_cast( p ) != NULL ) - { - // everything ok, so return pointer - return dynamic_cast( p ); - } - - // not quite... so delete plugin and return dummy instrument + if(keyFromDnd) + Q_ASSERT(!key); + // copy from above // TODO! common cleaner func + Plugin * p = Plugin::instantiateWithKey(_plugin_name, _instrument_track, key, keyFromDnd); + if(dynamic_cast(p)) + return dynamic_cast(p); delete p; return( new DummyInstrument( _instrument_track ) ); } diff --git a/src/core/InstrumentFunctions.cpp b/src/core/InstrumentFunctions.cpp index a2aecb9c9..70e2c5e80 100644 --- a/src/core/InstrumentFunctions.cpp +++ b/src/core/InstrumentFunctions.cpp @@ -349,6 +349,8 @@ void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n ) return; } + // Set master note if not playing arp note or it will play as an ordinary note + _n->setMasterNote(); const int selected_arp = m_arpModel.value(); @@ -401,8 +403,6 @@ void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n ) if( m_arpModeModel.value() == SortMode && ( ( cur_frame / arp_frames ) % total_range ) / range != (f_cnt_t) _n->index() ) { - // Set master note if not playing arp note or it will play as an ordinary note - _n->setMasterNote(); // update counters frames_processed += arp_frames; cur_frame += arp_frames; @@ -414,9 +414,6 @@ void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n ) { if( 100 * ( (float) rand() / (float)( RAND_MAX + 1.0f ) ) < m_arpSkipModel.value() ) { - // Set master note to prevent the note to extend over skipped notes - // This may only be needed for lb302 - _n->setMasterNote(); // update counters frames_processed += arp_frames; cur_frame += arp_frames; @@ -517,13 +514,6 @@ void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n ) frames_processed += arp_frames; cur_frame += arp_frames; } - - // make sure note is handled as arp-base-note, even - // if we didn't add a sub-note so far - if( m_arpModeModel.value() != FreeMode ) - { - _n->setMasterNote(); - } } diff --git a/src/core/LadspaControl.cpp b/src/core/LadspaControl.cpp index cf8c6e468..731241b85 100644 --- a/src/core/LadspaControl.cpp +++ b/src/core/LadspaControl.cpp @@ -42,7 +42,8 @@ LadspaControl::LadspaControl( Model * _parent, port_desc_t * _port, if( m_link ) { connect( &m_linkEnabledModel, SIGNAL( dataChanged() ), - this, SLOT( linkStateChanged() ) ); + this, SLOT( linkStateChanged() ), + Qt::DirectConnection ); } switch( m_port->data_type ) diff --git a/src/core/LadspaManager.cpp b/src/core/LadspaManager.cpp index 176fde18b..febbe5a91 100644 --- a/src/core/LadspaManager.cpp +++ b/src/core/LadspaManager.cpp @@ -40,7 +40,7 @@ LadspaManager::LadspaManager() { // Make sure plugin search paths are set up - PluginFactory::instance(); + PluginFactory::setupSearchPaths(); QStringList ladspaDirectories = QString( getenv( "LADSPA_PATH" ) ). split( LADSPA_PATH_SEPERATOR ); @@ -103,7 +103,7 @@ LadspaManager::LadspaManager() { m_sortedPlugins.append( qMakePair( getName( *it ), *it ) ); } - qSort( m_sortedPlugins ); + std::sort( m_sortedPlugins.begin(), m_sortedPlugins.end() ); } diff --git a/src/core/LfoController.cpp b/src/core/LfoController.cpp index c1c81119f..2b2db2f14 100644 --- a/src/core/LfoController.cpp +++ b/src/core/LfoController.cpp @@ -49,12 +49,12 @@ LfoController::LfoController( Model * _parent ) : { setSampleExact( true ); connect( &m_waveModel, SIGNAL( dataChanged() ), - this, SLOT( updateSampleFunction() ) ); + this, SLOT( updateSampleFunction() ), Qt::DirectConnection ); connect( &m_speedModel, SIGNAL( dataChanged() ), - this, SLOT( updateDuration() ) ); + this, SLOT( updateDuration() ), Qt::DirectConnection ); connect( &m_multiplierModel, SIGNAL( dataChanged() ), - this, SLOT( updateDuration() ) ); + this, SLOT( updateDuration() ), Qt::DirectConnection ); connect( Engine::mixer(), SIGNAL( sampleRateChanged() ), this, SLOT( updateDuration() ) ); diff --git a/src/core/MeterModel.cpp b/src/core/MeterModel.cpp index 87b1b950a..30db26d9b 100644 --- a/src/core/MeterModel.cpp +++ b/src/core/MeterModel.cpp @@ -33,9 +33,9 @@ MeterModel::MeterModel( ::Model * _parent ) : m_denominatorModel( 4, 1, 32, this, tr( "Denominator" ) ) { connect( &m_numeratorModel, SIGNAL( dataChanged() ), - this, SIGNAL( dataChanged() ) ); + this, SIGNAL( dataChanged() ), Qt::DirectConnection ); connect( &m_denominatorModel, SIGNAL( dataChanged() ), - this, SIGNAL( dataChanged() ) ); + this, SIGNAL( dataChanged() ), Qt::DirectConnection ); } diff --git a/src/core/MixHelpers.cpp b/src/core/MixHelpers.cpp index e1a2e092f..de1c5cfc3 100644 --- a/src/core/MixHelpers.cpp +++ b/src/core/MixHelpers.cpp @@ -23,9 +23,17 @@ */ #include "MixHelpers.h" + +#include + #include "lmms_math.h" #include "ValueBuffer.h" +#include + + +static bool s_NaNHandler; + namespace MixHelpers { @@ -68,10 +76,24 @@ bool isSilent( const sampleFrame* src, int frames ) return true; } +bool useNaNHandler() +{ + return s_NaNHandler; +} + +void setNaNHandler( bool use ) +{ + s_NaNHandler = use; +} /*! \brief Function for sanitizing a buffer of infs/nans - returns true if those are found */ bool sanitize( sampleFrame * src, int frames ) { + if( !useNaNHandler() ) + { + return false; + } + bool found = false; for( int f = 0; f < frames; ++f ) { @@ -79,12 +101,23 @@ bool sanitize( sampleFrame * src, int frames ) { if( isinf( src[f][c] ) || isnan( src[f][c] ) ) { - src[f][c] = 0.0f; + #ifdef LMMS_DEBUG + printf("Bad data, clearing buffer. frame: "); + printf("%d: value %f\n", f, src[f][c]); + #endif + for( int f = 0; f < frames; ++f ) + { + for( int c = 0; c < 2; ++c ) + { + src[f][c] = 0.0f; + } + } found = true; + return found; } else { - src[f][c] = qBound( -4.0f, src[f][c], 4.0f ); + src[f][c] = qBound( -1000.0f, src[f][c], 1000.0f ); } } } @@ -168,6 +201,13 @@ void addMultipliedByBuffers( sampleFrame* dst, const sampleFrame* src, ValueBuff void addSanitizedMultipliedByBuffer( sampleFrame* dst, const sampleFrame* src, float coeffSrc, ValueBuffer * coeffSrcBuf, int frames ) { + if ( !useNaNHandler() ) + { + addMultipliedByBuffer( dst, src, coeffSrc, coeffSrcBuf, + frames ); + return; + } + for( int f = 0; f < frames; ++f ) { dst[f][0] += ( isinf( src[f][0] ) || isnan( src[f][0] ) ) ? 0.0f : src[f][0] * coeffSrc * coeffSrcBuf->values()[f]; @@ -177,6 +217,13 @@ void addSanitizedMultipliedByBuffer( sampleFrame* dst, const sampleFrame* src, f void addSanitizedMultipliedByBuffers( sampleFrame* dst, const sampleFrame* src, ValueBuffer * coeffSrcBuf1, ValueBuffer * coeffSrcBuf2, int frames ) { + if ( !useNaNHandler() ) + { + addMultipliedByBuffers( dst, src, coeffSrcBuf1, coeffSrcBuf2, + frames ); + return; + } + for( int f = 0; f < frames; ++f ) { dst[f][0] += ( isinf( src[f][0] ) || isnan( src[f][0] ) ) @@ -205,6 +252,12 @@ struct AddSanitizedMultipliedOp void addSanitizedMultiplied( sampleFrame* dst, const sampleFrame* src, float coeffSrc, int frames ) { + if ( !useNaNHandler() ) + { + addMultiplied( dst, src, coeffSrc, frames ); + return; + } + run<>( dst, src, frames, AddSanitizedMultipliedOp(coeffSrc) ); } diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index 3298d3dd0..3f22a22e1 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -186,8 +186,8 @@ Mixer::~Mixer() } delete m_fifo; - delete m_audioDev; delete m_midiClient; + delete m_audioDev; for( int i = 0; i < 3; i++ ) { @@ -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" ) ); @@ -393,7 +393,7 @@ const surroundSampleFrame * Mixer::renderNextBuffer() ConstPlayHandleList::Iterator it_rem = m_playHandlesToRemove.begin(); while( it_rem != m_playHandlesToRemove.end() ) { - PlayHandleList::Iterator it = qFind( m_playHandles.begin(), m_playHandles.end(), *it_rem ); + PlayHandleList::Iterator it = std::find( m_playHandles.begin(), m_playHandles.end(), *it_rem ); if( it != m_playHandles.end() ) { @@ -534,10 +534,10 @@ void Mixer::clearInternal() -void Mixer::getPeakValues( sampleFrame * _ab, const f_cnt_t _frames, float & peakLeft, float & peakRight ) const +Mixer::StereoSample Mixer::getPeakValues(sampleFrame * _ab, const f_cnt_t _frames) const { - peakLeft = 0.0f; - peakRight = 0.0f; + sample_t peakLeft = 0.0f; + sample_t peakRight = 0.0f; for( f_cnt_t f = 0; f < _frames; ++f ) { @@ -553,6 +553,8 @@ void Mixer::getPeakValues( sampleFrame * _ab, const f_cnt_t _frames, float & pea peakRight = absRight; } } + + return StereoSample(peakLeft, peakRight); } @@ -575,53 +577,59 @@ void Mixer::changeQuality( const struct qualitySettings & _qs ) -void Mixer::setAudioDevice( AudioDevice * _dev ) +void Mixer::doSetAudioDevice( AudioDevice * _dev ) { - stopProcessing(); + // TODO: Use shared_ptr here in the future. + // Currently, this is safe, because this is only called by + // ProjectRenderer, and after ProjectRenderer calls this function, + // it does not access the old device anymore. + if( m_audioDev != m_oldAudioDev ) {delete m_audioDev;} - if( _dev == NULL ) + if( _dev ) + { + m_audioDev = _dev; + } + else { printf( "param _dev == NULL in Mixer::setAudioDevice(...). " "Trying any working audio-device\n" ); m_audioDev = tryAudioDevices(); } - else - { - m_audioDev = _dev; - } - - emit sampleRateChanged(); - - startProcessing(); } void Mixer::setAudioDevice( AudioDevice * _dev, - const struct qualitySettings & _qs, - bool _needs_fifo ) + bool startNow ) +{ + stopProcessing(); + + doSetAudioDevice( _dev ); + + emit sampleRateChanged(); + + if (startNow) {startProcessing();} +} + + + + +void Mixer::setAudioDevice(AudioDevice * _dev, + const struct qualitySettings & _qs, + bool _needs_fifo, + bool startNow) { - // don't delete the audio-device stopProcessing(); m_qualitySettings = _qs; - if( _dev == NULL ) - { - printf( "param _dev == NULL in Mixer::setAudioDevice(...). " - "Trying any working audio-device\n" ); - m_audioDev = tryAudioDevices(); - } - else - { - m_audioDev = _dev; - } + doSetAudioDevice( _dev ); emit qualitySettingsChanged(); emit sampleRateChanged(); - startProcessing( _needs_fifo ); + if (startNow) {startProcessing( _needs_fifo );} } @@ -640,7 +648,7 @@ void Mixer::storeAudioDevice() void Mixer::restoreAudioDevice() { - if( m_oldAudioDev != NULL ) + if( m_oldAudioDev && m_audioDev != m_oldAudioDev ) { stopProcessing(); delete m_audioDev; @@ -648,9 +656,9 @@ void Mixer::restoreAudioDevice() m_audioDev = m_oldAudioDev; emit sampleRateChanged(); - m_oldAudioDev = NULL; startProcessing(); } + m_oldAudioDev = NULL; } @@ -659,7 +667,7 @@ void Mixer::restoreAudioDevice() void Mixer::removeAudioPort( AudioPort * _port ) { requestChangeInModel(); - QVector::Iterator it = qFind( m_audioPorts.begin(), + QVector::Iterator it = std::find( m_audioPorts.begin(), m_audioPorts.end(), _port ); if( it != m_audioPorts.end() ) @@ -720,7 +728,7 @@ void Mixer::removePlayHandle( PlayHandle * _ph ) } } // Now check m_playHandles - PlayHandleList::Iterator it = qFind( m_playHandles.begin(), + PlayHandleList::Iterator it = std::find( m_playHandles.begin(), m_playHandles.end(), _ph ); if( it != m_playHandles.end() ) { @@ -823,20 +831,146 @@ void Mixer::runChangesInModel() if( m_changesSignal ) { m_waitChangesMutex.lock(); + // allow changes in the model from other threads ... m_changesRequestCondition.wakeOne(); + // ... and wait until they are done m_changesMixerCondition.wait( &m_waitChangesMutex ); m_waitChangesMutex.unlock(); } } +bool Mixer::isAudioDevNameValid(QString name) +{ +#ifdef LMMS_HAVE_SDL + if (name == AudioSdl::name()) + { + return true; + } +#endif +#ifdef LMMS_HAVE_ALSA + if (name == AudioAlsa::name()) + { + return true; + } +#endif + + +#ifdef LMMS_HAVE_PULSEAUDIO + if (name == AudioPulseAudio::name()) + { + return true; + } +#endif + + +#ifdef LMMS_HAVE_OSS + if (name == AudioOss::name()) + { + return true; + } +#endif + +#ifdef LMMS_HAVE_SNDIO + if (name == AudioSndio::name()) + { + return true; + } +#endif + +#ifdef LMMS_HAVE_JACK + if (name == AudioJack::name()) + { + return true; + } +#endif + + +#ifdef LMMS_HAVE_PORTAUDIO + if (name == AudioPortAudio::name()) + { + return true; + } +#endif + + +#ifdef LMMS_HAVE_SOUNDIO + if (name == AudioSoundIo::name()) + { + return true; + } +#endif + + if (name == AudioDummy::name()) + { + return true; + } + + return false; +} + +bool Mixer::isMidiDevNameValid(QString name) +{ +#ifdef LMMS_HAVE_ALSA + if (name == MidiAlsaSeq::name() || name == MidiAlsaRaw::name()) + { + return true; + } +#endif + +#ifdef LMMS_HAVE_JACK + if (name == MidiJack::name()) + { + return true; + } +#endif + +#ifdef LMMS_HAVE_OSS + if (name == MidiOss::name()) + { + return true; + } +#endif + +#ifdef LMMS_HAVE_SNDIO + if (name == MidiSndio::name()) + { + return true; + } +#endif + +#ifdef LMMS_BUILD_WIN32 + if (name == MidiWinMM::name()) + { + return true; + } +#endif + +#ifdef LMMS_BUILD_APPLE + if (name == MidiApple::name()) + { + return true; + } +#endif + + if (name == MidiDummy::name()) + { + return true; + } + + return false; +} AudioDevice * Mixer::tryAudioDevices() { bool success_ful = false; AudioDevice * dev = NULL; QString dev_name = ConfigManager::inst()->value( "mixer", "audiodev" ); + if( !isAudioDevNameValid( dev_name ) ) + { + dev_name = ""; + } m_audioDevStartFailed = false; @@ -980,6 +1114,10 @@ MidiClient * Mixer::tryMidiClients() { QString client_name = ConfigManager::inst()->value( "mixer", "mididev" ); + if( !isMidiDevNameValid( client_name ) ) + { + client_name = ""; + } #ifdef LMMS_HAVE_ALSA if( client_name == MidiAlsaSeq::name() || client_name == "" ) @@ -1109,7 +1247,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 ); @@ -1128,7 +1266,9 @@ void Mixer::fifoWriter::run() write( buffer ); } + // Let audio backend stop processing write( NULL ); + m_fifo->waitUntilRead(); } @@ -1148,5 +1288,3 @@ void Mixer::fifoWriter::write( surroundSampleFrame * buffer ) m_mixer->m_doChangesMutex.unlock(); } - - diff --git a/src/core/MixerWorkerThread.cpp b/src/core/MixerWorkerThread.cpp index 9632d22c7..52041d76e 100644 --- a/src/core/MixerWorkerThread.cpp +++ b/src/core/MixerWorkerThread.cpp @@ -24,7 +24,6 @@ #include "MixerWorkerThread.h" -#include #include #include #include @@ -33,6 +32,10 @@ #include "ThreadableJob.h" #include "Mixer.h" +#if defined(LMMS_HOST_X86) || defined(LMMS_HOST_X86_64) +#include +#endif + MixerWorkerThread::JobQueue MixerWorkerThread::globalJobQueue; QWaitCondition * MixerWorkerThread::queueReadyWaitCond = NULL; QList MixerWorkerThread::workerThreads; diff --git a/src/core/Model.cpp b/src/core/Model.cpp index 04a1f2f33..597d0340d 100644 --- a/src/core/Model.cpp +++ b/src/core/Model.cpp @@ -33,7 +33,7 @@ QString Model::fullDisplayName() const const QString p = parentModel()->fullDisplayName(); if( n.isEmpty() && p.isEmpty() ) { - return QString::null; + return QString(); } else if( p.isEmpty() ) { diff --git a/src/core/ModelVisitor.cpp b/src/core/ModelVisitor.cpp new file mode 100644 index 000000000..4036f56e0 --- /dev/null +++ b/src/core/ModelVisitor.cpp @@ -0,0 +1,44 @@ +/* + * ModelVisitor.cpp - visitors for automatable models + * + * Copyright (c) 2019-2019 Johannes Lorenz + * + * 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. + * + */ + +#include "ModelVisitor.h" + +#include "AutomatableModel.h" +#include "ComboBoxModel.h" +#include "TempoSyncKnobModel.h" + +void ModelVisitor::visit(BoolModel &m) { up(m); } +void ModelVisitor::visit(IntModel &m) { up(m); } +void ModelVisitor::visit(FloatModel &m) { up(m); } +void ModelVisitor::visit(ComboBoxModel &m) { up(m); } +void ModelVisitor::visit(TempoSyncKnobModel &m) { up(m); } + +void ConstModelVisitor::visit(const BoolModel &m) { up(m); } +void ConstModelVisitor::visit(const IntModel &m) { up(m); } +void ConstModelVisitor::visit(const FloatModel &m) { up(m); } +void ConstModelVisitor::visit(const ComboBoxModel &m) { up(m); } +void ConstModelVisitor::visit(const TempoSyncKnobModel &m) { up(m); } + +ModelVisitor::~ModelVisitor() {} +ConstModelVisitor::~ConstModelVisitor() {} diff --git a/src/core/NotePlayHandle.cpp b/src/core/NotePlayHandle.cpp index 6379ad769..9f934c619 100644 --- a/src/core/NotePlayHandle.cpp +++ b/src/core/NotePlayHandle.cpp @@ -62,6 +62,7 @@ NotePlayHandle::NotePlayHandle( InstrumentTrack* instrumentTrack, m_subNotes(), m_released( false ), m_releaseStarted( false ), + m_hasMidiNote( false ), m_hasParent( parent != NULL ), m_parent( parent ), m_hadChildren( false ), @@ -105,17 +106,6 @@ NotePlayHandle::NotePlayHandle( InstrumentTrack* instrumentTrack, m_instrumentTrack->midiNoteOn( *this ); } - if( hasParent() || ! m_instrumentTrack->isArpeggioEnabled() ) - { - const int baseVelocity = m_instrumentTrack->midiPort()->baseVelocity(); - - // send MidiNoteOn event - m_instrumentTrack->processOutEvent( - MidiEvent( MidiNoteOn, midiChannel(), midiKey(), midiVelocity( baseVelocity ) ), - MidiTime::fromFrames( offset(), Engine::framesPerTick() ), - offset() ); - } - if( m_instrumentTrack->instrument()->flags() & Instrument::IsSingleStreamed ) { setUsesBuffer( false ); @@ -177,11 +167,6 @@ void NotePlayHandle::setVolume( volume_t _volume ) void NotePlayHandle::setPanning( panning_t panning ) { Note::setPanning( panning ); - - MidiEvent event( MidiMetaEvent, midiChannel(), midiKey(), panningToMidi( panning ) ); - event.setMetaEvent( MidiNotePanning ); - - m_instrumentTrack->processOutEvent( event ); } @@ -210,6 +195,26 @@ void NotePlayHandle::play( sampleFrame * _working_buffer ) } lock(); + + /* 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; + + const int baseVelocity = m_instrumentTrack->midiPort()->baseVelocity(); + + // send MidiNoteOn event + m_instrumentTrack->processOutEvent( + MidiEvent( MidiNoteOn, midiChannel(), midiKey(), midiVelocity( baseVelocity ) ), + MidiTime::fromFrames( offset(), Engine::framesPerTick() ), + offset() ); + } + if( m_frequencyNeedsUpdate ) { updateFrequency(); @@ -235,13 +240,6 @@ void NotePlayHandle::play( sampleFrame * _working_buffer ) // decreasing release of an instrument-track while the note is active if( framesLeft() > 0 ) { - // clear offset frames if we're at the first period - // skip for single-streamed instruments, because in their case NPH::play() could be called from an IPH without a buffer argument - // ... also, they don't actually render the sound in NPH's, which is an even better reason to skip... - if( m_totalFramesPlayed == 0 && ! ( m_instrumentTrack->instrument()->flags() & Instrument::IsSingleStreamed ) ) - { - memset( _working_buffer, 0, sizeof( sampleFrame ) * offset() ); - } // play note! m_instrumentTrack->playNote( this, _working_buffer ); } @@ -369,8 +367,10 @@ void NotePlayHandle::noteOff( const f_cnt_t _s ) m_framesBeforeRelease = _s; m_releaseFramesToDo = qMax( 0, actualReleaseFramesToDo() ); - if( hasParent() || ! m_instrumentTrack->isArpeggioEnabled() ) + if( m_hasMidiNote ) { + m_hasMidiNote = false; + // send MidiNoteOff event m_instrumentTrack->processOutEvent( MidiEvent( MidiNoteOff, midiChannel(), midiKey(), 0 ), @@ -579,13 +579,9 @@ NotePlayHandle * NotePlayHandleManager::acquire( InstrumentTrack* instrumentTrac int midiEventChannel, NotePlayHandle::Origin origin ) { - if( s_availableIndex < 0 ) - { - s_mutex.lockForWrite(); - if( s_availableIndex < 0 ) extend( NPH_CACHE_INCREMENT ); - s_mutex.unlock(); - } - s_mutex.lockForRead(); + // TODO: use some lockless data structures + s_mutex.lockForWrite(); + if (s_availableIndex < 0) { extend(NPH_CACHE_INCREMENT); } NotePlayHandle * nph = s_available[s_availableIndex--]; s_mutex.unlock(); diff --git a/src/core/PeakController.cpp b/src/core/PeakController.cpp index 9e5e654a6..b2e3bc921 100644 --- a/src/core/PeakController.cpp +++ b/src/core/PeakController.cpp @@ -53,8 +53,10 @@ PeakController::PeakController( Model * _parent, this, SLOT( handleDestroyedEffect( ) ) ); } connect( Engine::mixer(), SIGNAL( sampleRateChanged() ), this, SLOT( updateCoeffs() ) ); - connect( m_peakEffect->attackModel(), SIGNAL( dataChanged() ), this, SLOT( updateCoeffs() ) ); - connect( m_peakEffect->decayModel(), SIGNAL( dataChanged() ), this, SLOT( updateCoeffs() ) ); + connect( m_peakEffect->attackModel(), SIGNAL( dataChanged() ), + this, SLOT( updateCoeffs() ), Qt::DirectConnection ); + connect( m_peakEffect->decayModel(), SIGNAL( dataChanged() ), + this, SLOT( updateCoeffs() ), Qt::DirectConnection ); m_coeffNeedsUpdate = true; } diff --git a/src/core/Plugin.cpp b/src/core/Plugin.cpp index b479d7d8d..411f6fe58 100644 --- a/src/core/Plugin.cpp +++ b/src/core/Plugin.cpp @@ -22,12 +22,14 @@ * */ +#include "Plugin.h" + +#include #include #include #include #include -#include "Plugin.h" #include "embed.h" #include "Engine.h" #include "GuiApplication.h" @@ -53,10 +55,12 @@ static Plugin::Descriptor dummyPluginDescriptor = -Plugin::Plugin( const Descriptor * descriptor, Model * parent ) : - Model( parent ), +Plugin::Plugin(const Descriptor * descriptor, Model * parent, const + Descriptor::SubPluginFeatures::Key* key) : + Model(parent), JournallingObject(), - m_descriptor( descriptor ) + m_descriptor(descriptor), + m_key(key ? *key : Descriptor::SubPluginFeatures::Key(m_descriptor)) { if( m_descriptor == NULL ) { @@ -74,6 +78,97 @@ Plugin::~Plugin() +template +T use_this_or(T this_param, T or_param) +{ + return this_param ? this_param : or_param; +} + + + + +QString use_this_or(QString this_param, QString or_param) +{ + return this_param.isNull() ? or_param : this_param; +} + + + + +QString Plugin::displayName() const +{ + return Model::displayName().isEmpty() // currently always empty + ? (m_descriptor->subPluginFeatures && m_key.isValid()) + // get from sub plugin + ? m_key.displayName() + // get from plugin + : m_descriptor->displayName + : Model::displayName(); +} + + + + +const PixmapLoader* Plugin::logo() const +{ + return (m_descriptor->subPluginFeatures && m_key.isValid()) + ? m_key.logo() + : m_descriptor->logo; +} + + + + +QString Plugin::Descriptor::SubPluginFeatures::Key::additionalFileExtensions() const +{ + Q_ASSERT(isValid()); + return desc->subPluginFeatures + // get from sub plugin + ? desc->subPluginFeatures->additionalFileExtensions(*this) + // no sub plugin, so no *additional* file extensions + : QString(); +} + + + + +QString Plugin::Descriptor::SubPluginFeatures::Key::displayName() const +{ + Q_ASSERT(isValid()); + return desc->subPluginFeatures + // get from sub plugin + ? use_this_or(desc->subPluginFeatures->displayName(*this), + QString::fromUtf8(desc->displayName)) + // get from plugin + : desc->displayName; +} + + + + +const PixmapLoader* Plugin::Descriptor::SubPluginFeatures::Key::logo() const +{ + Q_ASSERT(isValid()); + return desc->subPluginFeatures + ? use_this_or(desc->subPluginFeatures->logo(*this), desc->logo) + : desc->logo; +} + + + + +QString Plugin::Descriptor::SubPluginFeatures::Key::description() const +{ + Q_ASSERT(isValid()); + return desc->subPluginFeatures + ? use_this_or(desc->subPluginFeatures->description(*this), + QString::fromUtf8(desc->description)) + : desc->description; +} + + + + void Plugin::loadFile( const QString & ) { } @@ -90,10 +185,38 @@ AutomatableModel * Plugin::childModel( const QString & ) #include "PluginFactory.h" -Plugin * Plugin::instantiate( const QString& pluginName, Model * parent, - void * data ) +Plugin * Plugin::instantiateWithKey(const QString& pluginName, Model * parent, + const Descriptor::SubPluginFeatures::Key *key, + bool keyFromDnd) +{ + if(keyFromDnd) + Q_ASSERT(!key); + const Descriptor::SubPluginFeatures::Key *keyPtr = keyFromDnd + ? static_cast(Engine::pickDndPluginKey()) + : key; + const PluginFactory::PluginInfo& pi = pluginFactory->pluginInfo(pluginName.toUtf8()); + if(keyPtr) + { + // descriptor is not yet set when loading - set it now + Descriptor::SubPluginFeatures::Key keyCopy = *keyPtr; + keyCopy.desc = pi.descriptor; + return Plugin::instantiate(pluginName, parent, &keyCopy); + } + else + return Plugin::instantiate(pluginName, parent, + // the keys are never touched anywhere + const_cast(keyPtr)); +} + + + + +Plugin * Plugin::instantiate(const QString& pluginName, Model * parent, + void *data) { const PluginFactory::PluginInfo& pi = pluginFactory->pluginInfo(pluginName.toUtf8()); + + Plugin* inst; if( pi.isNull() ) { if( gui ) @@ -104,23 +227,31 @@ Plugin * Plugin::instantiate( const QString& pluginName, Model * parent, arg( pluginName ).arg( pluginFactory->errorString(pluginName) ), QMessageBox::Ok | QMessageBox::Default ); } - return new DummyPlugin(); + inst = new DummyPlugin(); } - - InstantiationHook instantiationHook = ( InstantiationHook ) pi.library->resolve( "lmms_plugin_main" ); - if( instantiationHook == NULL ) + else { - if( gui ) + InstantiationHook instantiationHook; + if ((instantiationHook = ( InstantiationHook ) pi.library->resolve( "lmms_plugin_main" ))) { - QMessageBox::information( NULL, - tr( "Error while loading plugin" ), - tr( "Failed to load plugin \"%1\"!").arg( pluginName ), - QMessageBox::Ok | QMessageBox::Default ); + inst = instantiationHook(parent, data); + if(!inst) { + inst = new DummyPlugin(); + } + } + else + { + if( gui ) + { + QMessageBox::information( NULL, + tr( "Error while loading plugin" ), + tr( "Failed to load plugin \"%1\"!").arg( pluginName ), + QMessageBox::Ok | QMessageBox::Default ); + } + inst = new DummyPlugin(); } - return new DummyPlugin(); } - Plugin * inst = instantiationHook( parent, data ); return inst; } diff --git a/src/core/PluginFactory.cpp b/src/core/PluginFactory.cpp index a87e49270..abf642122 100644 --- a/src/core/PluginFactory.cpp +++ b/src/core/PluginFactory.cpp @@ -28,8 +28,11 @@ #include #include #include +#include "lmmsconfig.h" #include "ConfigManager.h" +#include "Plugin.h" +#include "embed.h" #ifdef LMMS_BUILD_WIN32 QStringList nameFilters("*.dll"); @@ -45,6 +48,16 @@ qint64 qHash(const QFileInfo& fi) std::unique_ptr PluginFactory::s_instance; PluginFactory::PluginFactory() +{ + setupSearchPaths(); + discoverPlugins(); +} + +PluginFactory::~PluginFactory() +{ +} + +void PluginFactory::setupSearchPaths() { // Adds a search path relative to the main executable if the path exists. auto addRelativeIfExists = [](const QString & path) { @@ -76,12 +89,6 @@ PluginFactory::PluginFactory() QDir::addSearchPath("plugins", env_path); QDir::addSearchPath("plugins", ConfigManager::inst()->workingDir() + "plugins"); - - discoverPlugins(); -} - -PluginFactory::~PluginFactory() -{ } PluginFactory* PluginFactory::instance() @@ -107,9 +114,9 @@ const PluginFactory::PluginInfoList& PluginFactory::pluginInfos() const return m_pluginInfos; } -const PluginFactory::PluginInfo PluginFactory::pluginSupportingExtension(const QString& ext) +const PluginFactory::PluginInfoAndKey PluginFactory::pluginSupportingExtension(const QString& ext) { - return m_pluginByExt.value(ext, PluginInfo()); + return m_pluginByExt.value(ext, PluginInfoAndKey()); } const PluginFactory::PluginInfo PluginFactory::pluginInfo(const char* name) const @@ -150,42 +157,78 @@ void PluginFactory::discoverPlugins() for (const QFileInfo& file : files) { auto library = std::make_shared(file.absoluteFilePath()); - if (! library->load()) { m_errors[file.baseName()] = library->errorString(); qWarning("%s", library->errorString().toLocal8Bit().data()); continue; } - if (library->resolve("lmms_plugin_main") == nullptr) { - continue; - } - QString descriptorName = file.baseName() + "_plugin_descriptor"; - if( descriptorName.left(3) == "lib" ) + Plugin::Descriptor* pluginDescriptor = nullptr; + if (library->resolve("lmms_plugin_main")) { - descriptorName = descriptorName.mid(3); + QString descriptorName = file.baseName() + "_plugin_descriptor"; + if( descriptorName.left(3) == "lib" ) + { + descriptorName = descriptorName.mid(3); + } + + pluginDescriptor = reinterpret_cast(library->resolve(descriptorName.toUtf8().constData())); + if(pluginDescriptor == nullptr) + { + qWarning() << qApp->translate("PluginFactory", "LMMS plugin %1 does not have a plugin descriptor named %2!"). + arg(file.absoluteFilePath()).arg(descriptorName); + continue; + } } - Plugin::Descriptor* pluginDescriptor = reinterpret_cast(library->resolve(descriptorName.toUtf8().constData())); - if(pluginDescriptor == nullptr) + if(pluginDescriptor) { - qWarning() << qApp->translate("PluginFactory", "LMMS plugin %1 does not have a plugin descriptor named %2!"). - arg(file.absoluteFilePath()).arg(descriptorName); - continue; + PluginInfo info; + info.file = file; + info.library = library; + info.descriptor = pluginDescriptor; + pluginInfos << info; + + auto addSupportedFileTypes = + [this](QString supportedFileTypes, + const PluginInfo& info, + const Plugin::Descriptor::SubPluginFeatures::Key* key = nullptr) + { + if(!supportedFileTypes.isNull()) + { + for (const QString& ext : supportedFileTypes.split(',')) + { + //qDebug() << "Plugin " << info.name() + // << "supports" << ext; + PluginInfoAndKey infoAndKey; + infoAndKey.info = info; + infoAndKey.key = key + ? *key + : Plugin::Descriptor::SubPluginFeatures::Key(); + m_pluginByExt.insert(ext, infoAndKey); + } + } + }; + + if (info.descriptor->supportedFileTypes) + addSupportedFileTypes(QString(info.descriptor->supportedFileTypes), info); + + if (info.descriptor->subPluginFeatures) + { + Plugin::Descriptor::SubPluginFeatures::KeyList + subPluginKeys; + info.descriptor->subPluginFeatures->listSubPluginKeys( + info.descriptor, + subPluginKeys); + for(const Plugin::Descriptor::SubPluginFeatures::Key& key + : subPluginKeys) + { + addSupportedFileTypes(key.additionalFileExtensions(), info, &key); + } + } + + descriptors.insert(info.descriptor->type, info.descriptor); } - - PluginInfo info; - info.file = file; - info.library = library; - info.descriptor = pluginDescriptor; - pluginInfos << info; - - for (const QString& ext : QString(info.descriptor->supportedFileTypes).split(',')) - { - m_pluginByExt.insert(ext, info); - } - - descriptors.insert(info.descriptor->type, info.descriptor); } m_pluginInfos = pluginInfos; diff --git a/src/core/PluginIssue.cpp b/src/core/PluginIssue.cpp new file mode 100644 index 000000000..4a8b2ee5b --- /dev/null +++ b/src/core/PluginIssue.cpp @@ -0,0 +1,72 @@ +/* + * PluginIssue.h - PluginIssue class + * + * Copyright (c) 2019 Johannes Lorenz + * + * 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. + * + */ + +#include + +#include "PluginIssue.h" + +const char *PluginIssue::msgFor(const PluginIssueType &it) +{ + switch (it) + { + case unknownPortFlow: + return "unknown port flow for mandatory port"; + case unknownPortType: + return "unknown port type for mandatory port"; + case tooManyInputChannels: + return "too many audio input channels"; + case tooManyOutputChannels: + return "too many audio output channels"; + case noOutputChannel: + return "no audio output channel"; + case portHasNoDef: + return "port is missing default value"; + case portHasNoMin: + return "port is missing min value"; + case portHasNoMax: + return "port is missing max value"; + case featureNotSupported: + return "required feature not supported"; + case badPortType: + return "unsupported port type"; + case noIssue: + return nullptr; + } + return nullptr; +} + + + + +QDebug operator<<(QDebug stream, const PluginIssue &iss) +{ + stream << PluginIssue::msgFor(iss.m_issueType); + if (iss.m_info.length()) + { + stream.nospace() << ": " << iss.m_info.c_str(); + } + return stream; +} + + diff --git a/src/core/PresetPreviewPlayHandle.cpp b/src/core/PresetPreviewPlayHandle.cpp index dc36819b7..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"; } @@ -137,8 +137,10 @@ PresetPreviewPlayHandle::PresetPreviewPlayHandle( const QString & _preset_file, suffix().toLower(); if( i == NULL || !i->descriptor()->supportsFileType( ext ) ) { + const PluginFactory::PluginInfoAndKey& infoAndKey = + pluginFactory->pluginSupportingExtension(ext); i = s_previewTC->previewInstrumentTrack()-> - loadInstrument(pluginFactory->pluginSupportingExtension(ext).name()); + loadInstrument(infoAndKey.info.name(), &infoAndKey.key); } if( i != NULL ) { diff --git a/src/core/ProjectJournal.cpp b/src/core/ProjectJournal.cpp index 57646aeaa..e3cd362cb 100644 --- a/src/core/ProjectJournal.cpp +++ b/src/core/ProjectJournal.cpp @@ -29,6 +29,8 @@ #include "JournallingObject.h" #include "Song.h" +//! Avoid clashes between loaded IDs (have the bit cleared) +//! and newly created IDs (have the bit set) static const int EO_ID_MSB = 1 << 23; const int ProjectJournal::MAX_UNDO_STATES = 100; // TODO: make this configurable in settings @@ -164,6 +166,11 @@ jo_id_t ProjectJournal::idToSave( jo_id_t id ) return id & ~EO_ID_MSB; } +jo_id_t ProjectJournal::idFromSave( jo_id_t id ) +{ + return id | EO_ID_MSB; +} + diff --git a/src/core/ProjectRenderer.cpp b/src/core/ProjectRenderer.cpp index adb715cfd..19bdf4be8 100644 --- a/src/core/ProjectRenderer.cpp +++ b/src/core/ProjectRenderer.cpp @@ -152,7 +152,7 @@ void ProjectRenderer::startProcessing() // Have to do mixer stuff with GUI-thread affinity in order to // make slots connected to sampleRateChanged()-signals being called immediately. Engine::mixer()->setAudioDevice( m_fileDev, - m_qualitySettings, false ); + m_qualitySettings, false, false ); start( #ifndef LMMS_BUILD_WIN32 @@ -168,7 +168,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 ); @@ -185,22 +185,17 @@ void ProjectRenderer::run() // Skip first empty buffer. Engine::mixer()->nextBuffer(); - const Song::PlayPos & exportPos = Engine::getSong()->getPlayPos( - Song::Mode_PlaySong ); m_progress = 0; - std::pair exportEndpoints = Engine::getSong()->getExportEndpoints(); - tick_t startTick = exportEndpoints.first.getTicks(); - tick_t endTick = exportEndpoints.second.getTicks(); - tick_t lengthTicks = endTick - startTick; + + // Now start processing + Engine::mixer()->startProcessing(false); // Continually track and emit progress percentage to listeners. - while( exportPos.getTicks() < endTick && - Engine::getSong()->isExporting() == true - && !m_abort ) + while (!Engine::getSong()->isExportDone() && !m_abort) { m_fileDev->processNextBuffer(); - const int nprog = lengthTicks == 0 ? 100 : (exportPos.getTicks()-startTick) * 100 / lengthTicks; - if( m_progress != nprog ) + const int nprog = Engine::getSong()->getExportProgress(); + if (m_progress != nprog) { m_progress = nprog; emit progressChanged( m_progress ); diff --git a/src/core/RemotePlugin.cpp b/src/core/RemotePlugin.cpp index 64b5e592d..23654d782 100644 --- a/src/core/RemotePlugin.cpp +++ b/src/core/RemotePlugin.cpp @@ -33,6 +33,7 @@ #include "Mixer.h" #include "Engine.h" +#include #include #ifndef SYNC_WITH_SHM_FIFO @@ -54,7 +55,10 @@ ProcessWatcher::ProcessWatcher( RemotePlugin * _p ) : void ProcessWatcher::run() { - while( !m_quit && (m_plugin->isRunning() || m_plugin->messagesLeft()) ) + m_plugin->m_process.start( m_plugin->m_exec, m_plugin->m_args ); + exec(); + m_plugin->m_process.moveToThread( m_plugin->thread() ); + while( !m_quit && m_plugin->messagesLeft() ) { msleep( 200 ); } @@ -62,6 +66,7 @@ void ProcessWatcher::run() { fprintf( stderr, "remote plugin died! invalidating now.\n" ); + m_plugin->invalidate(); } } @@ -78,7 +83,6 @@ RemotePlugin::RemotePlugin() : RemotePluginBase(), #endif m_failed( true ), - m_process(), m_watcher( this ), m_commMutex( QMutex::Recursive ), m_splitChannels( false ), @@ -120,6 +124,15 @@ RemotePlugin::RemotePlugin() : qWarning( "Unable to start the server." ); } #endif + + connect( &m_process, SIGNAL( finished( int, QProcess::ExitStatus ) ), + this, SLOT( processFinished( int, QProcess::ExitStatus ) ), + Qt::DirectConnection ); + connect( &m_process, SIGNAL( errorOccurred( QProcess::ProcessError ) ), + this, SLOT( processErrored( QProcess::ProcessError ) ), + Qt::DirectConnection ); + connect( &m_process, SIGNAL( finished( int, QProcess::ExitStatus ) ), + &m_watcher, SLOT( quit() ), Qt::DirectConnection ); } @@ -127,7 +140,7 @@ RemotePlugin::RemotePlugin() : RemotePlugin::~RemotePlugin() { - m_watcher.quit(); + m_watcher.stop(); m_watcher.wait(); if( m_failed == false ) @@ -201,6 +214,11 @@ bool RemotePlugin::init(const QString &pluginExecutable, return failed(); } + // ensure the watcher is ready in case we're running again + // (e.g. 32-bit VST plugins on Windows) + m_watcher.wait(); + m_watcher.reset(); + QStringList args; #ifdef SYNC_WITH_SHM_FIFO // swap in and out for bidirectional communication @@ -213,15 +231,15 @@ bool RemotePlugin::init(const QString &pluginExecutable, #ifndef DEBUG_REMOTE_PLUGIN m_process.setProcessChannelMode( QProcess::ForwardedChannels ); m_process.setWorkingDirectory( QCoreApplication::applicationDirPath() ); - m_process.start( exec, args ); + m_exec = exec; + m_args = args; + // we start the process on the watcher thread to work around QTBUG-8819 + m_process.moveToThread( &m_watcher ); m_watcher.start( QThread::LowestPriority ); #else qDebug() << exec << args; #endif - connect( &m_process, SIGNAL( finished( int, QProcess::ExitStatus ) ), - this, SLOT( processFinished( int, QProcess::ExitStatus ) ) ); - #ifndef SYNC_WITH_SHM_FIFO struct pollfd pollin; pollin.fd = m_server; @@ -454,11 +472,24 @@ void RemotePlugin::resizeSharedProcessingMemory() void RemotePlugin::processFinished( int exitCode, QProcess::ExitStatus exitStatus ) { + if ( exitStatus == QProcess::CrashExit ) + { + qCritical() << "Remote plugin crashed"; + } + else if ( exitCode ) + { + qCritical() << "Remote plugin exit code: " << exitCode; + } #ifndef SYNC_WITH_SHM_FIFO invalidate(); #endif } +void RemotePlugin::processErrored( QProcess::ProcessError err ) +{ + qCritical() << "Process error: " << err; +} + diff --git a/src/core/RenderManager.cpp b/src/core/RenderManager.cpp index 9cad4dd1e..019e14acf 100644 --- a/src/core/RenderManager.cpp +++ b/src/core/RenderManager.cpp @@ -103,7 +103,7 @@ void RenderManager::renderTracks() Track* tk = (*it); Track::TrackTypes type = tk->type(); - // Don't mute automation tracks + // Don't render automation tracks if ( tk->isMuted() == false && ( type == Track::InstrumentTrack || type == Track::SampleTrack ) ) { @@ -115,7 +115,11 @@ void RenderManager::renderTracks() for( auto it = t2.begin(); it != t2.end(); ++it ) { Track* tk = (*it); - if ( tk->isMuted() == false ) + Track::TrackTypes type = tk->type(); + + // Don't render automation tracks + if ( tk->isMuted() == false && + ( type == Track::InstrumentTrack || type == Track::SampleTrack ) ) { m_unmuted.push_back(tk); } diff --git a/src/core/SampleBuffer.cpp b/src/core/SampleBuffer.cpp index 9cde88cf5..d0c39b13a 100644 --- a/src/core/SampleBuffer.cpp +++ b/src/core/SampleBuffer.cpp @@ -73,7 +73,7 @@ SampleBuffer::SampleBuffer() : m_amplification( 1.0f ), m_reversed( false ), m_frequency( BaseFreq ), - m_sampleRate( Engine::mixer()->baseSampleRate() ) + m_sampleRate( mixerSampleRate () ) { connect( Engine::mixer(), SIGNAL( sampleRateChanged() ), this, SLOT( sampleRateChanged() ) ); @@ -143,6 +143,11 @@ void SampleBuffer::sampleRateChanged() update( true ); } +sample_rate_t SampleBuffer::mixerSampleRate() +{ + return Engine::mixer()->processingSampleRate(); +} + void SampleBuffer::update( bool _keep_settings ) { @@ -175,15 +180,10 @@ void SampleBuffer::update( bool _keep_settings ) else if( !m_audioFile.isEmpty() ) { QString file = tryToMakeAbsolute( m_audioFile ); -#ifdef LMMS_BUILD_WIN32 - char * f = qstrdup( file.toLocal8Bit().constData() ); -#else - char * f = qstrdup( file.toUtf8().constData() ); -#endif int_sample_t * buf = NULL; sample_t * fbuf = NULL; ch_cnt_t channels = DEFAULT_CHANNELS; - sample_rate_t samplerate = Engine::mixer()->baseSampleRate(); + sample_rate_t samplerate = mixerSampleRate(); m_frames = 0; const QFileInfo fileInfo( file ); @@ -193,10 +193,13 @@ void SampleBuffer::update( bool _keep_settings ) } else { + // Use QFile to handle unicode file names on Windows + QFile f(file); + f.open(QIODevice::ReadOnly); SNDFILE * snd_file; SF_INFO sf_info; sf_info.format = 0; - if( ( snd_file = sf_open( f, SFM_READ, &sf_info ) ) != NULL ) + if( ( snd_file = sf_open_fd( f.handle(), SFM_READ, &sf_info, false ) ) != NULL ) { f_cnt_t frames = sf_info.frames; int rate = sf_info.samplerate; @@ -206,6 +209,7 @@ void SampleBuffer::update( bool _keep_settings ) } sf_close( snd_file ); } + f.close(); } if( !fileLoadError ) @@ -216,28 +220,26 @@ void SampleBuffer::update( bool _keep_settings ) // decoder first if filename extension matches "ogg" if( m_frames == 0 && fileInfo.suffix() == "ogg" ) { - m_frames = decodeSampleOGGVorbis( f, buf, channels, samplerate ); + m_frames = decodeSampleOGGVorbis( file, buf, channels, samplerate ); } #endif if( m_frames == 0 ) { - m_frames = decodeSampleSF( f, fbuf, channels, + m_frames = decodeSampleSF( file, fbuf, channels, samplerate ); } #ifdef LMMS_HAVE_OGGVORBIS if( m_frames == 0 ) { - m_frames = decodeSampleOGGVorbis( f, buf, channels, + m_frames = decodeSampleOGGVorbis( file, buf, channels, samplerate ); } #endif if( m_frames == 0 ) { - m_frames = decodeSampleDS( f, buf, channels, + m_frames = decodeSampleDS( file, buf, channels, samplerate ); } - - delete[] f; } if ( m_frames == 0 || fileLoadError ) // if still no frames, bail @@ -288,7 +290,6 @@ void SampleBuffer::update( bool _keep_settings ) else { fprintf( stderr, "%s\n", message.toUtf8().constData() ); - exit( EXIT_FAILURE ); } } } @@ -369,11 +370,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 != Engine::mixer()->baseSampleRate() ) + if( _src_sr != mixerSampleRate() ) { SampleBuffer * resampled = resample( _src_sr, - Engine::mixer()->baseSampleRate() ); + mixerSampleRate() ); + + m_sampleRate = mixerSampleRate(); MM_FREE( m_data ); m_frames = resampled->frames(); m_data = MM_ALLOC( sampleFrame, m_frames ); @@ -388,12 +392,22 @@ 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(); + } } -f_cnt_t SampleBuffer::decodeSampleSF( const char * _f, +f_cnt_t SampleBuffer::decodeSampleSF(QString _f, sample_t * & _buf, ch_cnt_t & _channels, sample_rate_t & _samplerate ) @@ -404,7 +418,11 @@ f_cnt_t SampleBuffer::decodeSampleSF( const char * _f, f_cnt_t frames = 0; bool sf_rr = false; - if( ( snd_file = sf_open( _f, SFM_READ, &sf_info ) ) != NULL ) + + // Use QFile to handle unicode file names on Windows + QFile f(_f); + f.open(QIODevice::ReadOnly); + if( ( snd_file = sf_open_fd( f.handle(), SFM_READ, &sf_info, false ) ) != NULL ) { frames = sf_info.frames; @@ -430,6 +448,8 @@ f_cnt_t SampleBuffer::decodeSampleSF( const char * _f, "sample %s: %s", _f, sf_strerror( NULL ) ); #endif } + f.close(); + //write down either directly or convert i->f depending on file type if ( frames > 0 && _buf != NULL ) @@ -495,7 +515,7 @@ long qfileTellCallback( void * _udata ) -f_cnt_t SampleBuffer::decodeSampleOGGVorbis( const char * _f, +f_cnt_t SampleBuffer::decodeSampleOGGVorbis( QString _f, int_sample_t * & _buf, ch_cnt_t & _channels, sample_rate_t & _samplerate ) @@ -591,7 +611,7 @@ f_cnt_t SampleBuffer::decodeSampleOGGVorbis( const char * _f, -f_cnt_t SampleBuffer::decodeSampleDS( const char * _f, +f_cnt_t SampleBuffer::decodeSampleDS( QString _f, int_sample_t * & _buf, ch_cnt_t & _channels, sample_rate_t & _samplerate ) @@ -929,7 +949,7 @@ void SampleBuffer::visualize( QPainter & _p, const QRect & _dr, const float y_space = h*0.5f; const int nb_frames = focus_on_range ? _to_frame - _from_frame : m_frames; - const int fpp = tLimit( nb_frames / w, 1, 20 ); + const int fpp = qBound( 1, nb_frames / w, 20 ); QPointF * l = new QPointF[nb_frames / fpp + 1]; QPointF * r = new QPointF[nb_frames / fpp + 1]; int n = 0; @@ -1009,12 +1029,12 @@ QString SampleBuffer::openAudioFile() const { if( ofd.selectedFiles().isEmpty() ) { - return QString::null; + return QString(); } return tryToMakeRelative( ofd.selectedFiles()[0] ); } - return QString::null; + return QString(); } diff --git a/src/core/SamplePlayHandle.cpp b/src/core/SamplePlayHandle.cpp index 549a6c3a5..77a254cce 100644 --- a/src/core/SamplePlayHandle.cpp +++ b/src/core/SamplePlayHandle.cpp @@ -32,35 +32,37 @@ -SamplePlayHandle::SamplePlayHandle( SampleBuffer* sampleBuffer ) : +SamplePlayHandle::SamplePlayHandle( SampleBuffer* sampleBuffer , bool ownAudioPort ) : PlayHandle( TypeSamplePlayHandle ), m_sampleBuffer( sharedObject::ref( sampleBuffer ) ), m_doneMayReturnTrue( true ), m_frame( 0 ), - m_ownAudioPort( true ), + m_ownAudioPort( ownAudioPort ), m_defaultVolumeModel( DefaultVolume, MinVolume, MaxVolume, 1 ), m_volumeModel( &m_defaultVolumeModel ), m_track( NULL ), m_bbTrack( NULL ) { - setAudioPort( new AudioPort( "SamplePlayHandle", false ) ); + if (ownAudioPort) + { + setAudioPort( new AudioPort( "SamplePlayHandle", false ) ); + } } SamplePlayHandle::SamplePlayHandle( const QString& sampleFile ) : - SamplePlayHandle( new SampleBuffer( sampleFile ) ) + SamplePlayHandle( new SampleBuffer( sampleFile ) , true) { sharedObject::unref( m_sampleBuffer ); - setAudioPort( new AudioPort( "SamplePlayHandle", false ) ); } SamplePlayHandle::SamplePlayHandle( SampleTCO* tco ) : - SamplePlayHandle( tco->sampleBuffer() ) + SamplePlayHandle( tco->sampleBuffer() , false) { m_track = tco->getTrack(); setAudioPort( ( (SampleTrack *)tco->getTrack() )->audioPort() ); @@ -139,7 +141,7 @@ bool SamplePlayHandle::isFromTrack( const Track * _track ) const f_cnt_t SamplePlayHandle::totalFrames() const { - return ( m_sampleBuffer->endFrame() - m_sampleBuffer->startFrame() ) * ( Engine::mixer()->processingSampleRate() / Engine::mixer()->baseSampleRate() ); + return ( m_sampleBuffer->endFrame() - m_sampleBuffer->startFrame() ) * ( Engine::mixer()->processingSampleRate() / m_sampleBuffer->sampleRate() ); } diff --git a/src/core/Song.cpp b/src/core/Song.cpp index c670ade66..2fa7d716a 100644 --- a/src/core/Song.cpp +++ b/src/core/Song.cpp @@ -57,7 +57,7 @@ #include "PeakController.h" -tick_t MidiTime::s_ticksPerTact = DefaultTicksPerTact; +tick_t MidiTime::s_ticksPerBar = DefaultTicksPerBar; @@ -69,7 +69,7 @@ Song::Song() : m_globalGroove(GrooveFactory::create("none")), 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(), @@ -89,22 +89,24 @@ Song::Song() : m_patternToPlay( NULL ), m_loopPattern( false ), m_elapsedTicks( 0 ), - m_elapsedTacts( 0 ) + m_elapsedBars( 0 ), + m_loopRenderCount(1), + m_loopRenderRemaining(1) { for(int i = 0; i < Mode_Count; ++i) m_elapsedMilliSeconds[i] = 0; connect( &m_tempoModel, SIGNAL( dataChanged() ), - this, SLOT( setTempo() ) ); + this, SLOT( setTempo() ), Qt::DirectConnection ); connect( &m_tempoModel, SIGNAL( dataUnchanged() ), - this, SLOT( setTempo() ) ); + this, SLOT( setTempo() ), Qt::DirectConnection ); connect( &m_timeSigModel, SIGNAL( dataChanged() ), - this, SLOT( setTimeSignature() ) ); + this, SLOT( setTimeSignature() ), Qt::DirectConnection ); connect( Engine::mixer(), SIGNAL( sampleRateChanged() ), this, SLOT( updateFramesPerTick() ) ); connect( &m_masterVolumeModel, SIGNAL( dataChanged() ), - this, SLOT( masterVolumeChanged() ) ); + this, SLOT( masterVolumeChanged() ), Qt::DirectConnection ); /* connect( &m_masterPitchModel, SIGNAL( dataChanged() ), this, SLOT( masterPitchChanged() ) );*/ @@ -164,10 +166,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() ); @@ -191,6 +193,8 @@ void Song::savePos() void Song::processNextBuffer() { + m_vstSyncController.setPlaybackJumped( false ); + // if not playing, nothing to do if( m_playing == false ) { @@ -259,10 +263,19 @@ void Song::processNextBuffer() setToTime(tl->loopBegin()); m_playPos[m_playMode].setTicks( tl->loopBegin().getTicks() ); + + m_vstSyncController.setPlaybackJumped( true ); + emit updateSampleTracks(); } } + if( m_playPos[m_playMode].jumped() ) + { + m_vstSyncController.setPlaybackJumped( true ); + m_playPos[m_playMode].setJumped( false ); + } + f_cnt_t framesPlayed = 0; const float framesPerTick = Engine::framesPerTick(); @@ -277,22 +290,20 @@ void Song::processNextBuffer() int ticks = m_playPos[m_playMode].getTicks() + ( int )( currentFrame / framesPerTick ); - m_vstSyncController.setAbsolutePosition( ticks ); - - // 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 && @@ -300,27 +311,27 @@ 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); - m_vstSyncController.setAbsolutePosition( ticks ); + m_vstSyncController.setPlaybackJumped( true ); } } m_playPos[m_playMode].setTicks( ticks ); - if( checkLoop ) + if (checkLoop || m_loopRenderRemaining > 1) { m_vstSyncController.startCycle( tl->loopBegin().getTicks(), tl->loopEnd().getTicks() ); @@ -330,11 +341,14 @@ void Song::processNextBuffer() // beginning of the range if( m_playPos[m_playMode] >= tl->loopEnd() ) { - m_playPos[m_playMode].setTicks( tl->loopBegin().getTicks() ); + if (m_loopRenderRemaining > 1) + m_loopRenderRemaining--; + ticks = tl->loopBegin().getTicks(); + m_playPos[m_playMode].setTicks( ticks ); setToTime(tl->loopBegin()); - } - else if( m_playPos[m_playMode] == tl->loopEnd() - 1 ) - { + + m_vstSyncController.setPlaybackJumped( true ); + emit updateSampleTracks(); } } @@ -347,7 +361,17 @@ void Song::processNextBuffer() m_playPos[m_playMode].setCurrentFrame( currentFrame ); } - f_cnt_t framesToPlay = + if( framesPlayed == 0 ) + { + // update VST sync position after we've corrected frame/ + // tick count but before actually playing any frames + m_vstSyncController.setAbsolutePosition( + m_playPos[m_playMode].getTicks() + + m_playPos[m_playMode].currentFrame() + / (double) framesPerTick ); + } + + f_cnt_t framesToPlay = Engine::mixer()->framesPerPeriod() - framesPlayed; f_cnt_t framesLeft = ( f_cnt_t )framesPerTick - @@ -387,8 +411,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; } } @@ -464,29 +488,41 @@ void Song::setModified(bool value) } } -std::pair Song::getExportEndpoints() const +bool Song::isExportDone() const { - if ( m_renderBetweenMarkers ) + return !isExporting() || m_playPos[m_playMode] >= m_exportSongEnd; +} + +int Song::getExportProgress() const +{ + MidiTime pos = m_playPos[m_playMode]; + + if (pos >= m_exportSongEnd) { - return std::pair( - m_playPos[Mode_PlaySong].m_timeLine->loopBegin(), - m_playPos[Mode_PlaySong].m_timeLine->loopEnd() - ); + return 100; } - else if ( m_exportLoop ) + else if (pos <= m_exportSongBegin) { - return std::pair( MidiTime(0, 0), MidiTime(m_length, 0) ); + return 0; + } + else if (pos >= m_exportLoopEnd) + { + pos = (m_exportLoopBegin-m_exportSongBegin) + (m_exportLoopEnd - m_exportLoopBegin) * + m_loopRenderCount + (pos - m_exportLoopEnd); + } + else if ( pos >= m_exportLoopBegin ) + { + pos = (m_exportLoopBegin-m_exportSongBegin) + ((m_exportLoopEnd - m_exportLoopBegin) * + (m_loopRenderCount - m_loopRenderRemaining)) + (pos - m_exportLoopBegin); } else { - // if not exporting as a loop, we leave one bar of padding at the end of the song to accomodate reverb, etc. - return std::pair( MidiTime(0, 0), MidiTime(m_length+1, 0) ); + pos = (pos - m_exportSongBegin); } + + return (float)pos/(float)m_exportEffectiveLength*100.0f; } - - - void Song::playSong() { m_recording = false; @@ -587,7 +623,7 @@ void Song::updateLength() continue; } - const tact_t cur = ( *it )->length(); + const bar_t cur = ( *it )->length(); if( cur > m_length ) { m_length = cur; @@ -608,6 +644,7 @@ void Song::setPlayPos( tick_t ticks, PlayModes playMode ) m_elapsedMilliSeconds[playMode] += MidiTime::ticksToMilliseconds( ticks - ticksFromPlayMode, getTempo() ); m_playPos[playMode].setTicks( ticks ); m_playPos[playMode].setCurrentFrame( 0.0f ); + m_playPos[playMode].setJumped( true ); // send a signal if playposition changes during playback if( isPlaying() ) @@ -687,7 +724,10 @@ void Song::stop() m_playPos[m_playMode].setCurrentFrame( 0 ); m_vstSyncController.setPlaybackState( m_exporting ); - m_vstSyncController.setAbsolutePosition( m_playPos[m_playMode].getTicks() ); + m_vstSyncController.setAbsolutePosition( + m_playPos[m_playMode].getTicks() + + m_playPos[m_playMode].currentFrame() + / (double) Engine::framesPerTick() ); // remove all note-play-handles that are active Engine::mixer()->clear(); @@ -704,15 +744,41 @@ void Song::stop() void Song::startExport() { stop(); - if(m_renderBetweenMarkers) + if (m_renderBetweenMarkers) { + m_exportSongBegin = m_exportLoopBegin = m_playPos[Mode_PlaySong].m_timeLine->loopBegin(); + m_exportSongEnd = m_exportLoopEnd = m_playPos[Mode_PlaySong].m_timeLine->loopEnd(); + m_playPos[Mode_PlaySong].setTicks( m_playPos[Mode_PlaySong].m_timeLine->loopBegin().getTicks() ); } else { + m_exportSongEnd = MidiTime(m_length, 0); + + // Handle potentially ridiculous loop points gracefully. + if (m_loopRenderCount > 1 && m_playPos[Mode_PlaySong].m_timeLine->loopEnd() > m_exportSongEnd) + { + m_exportSongEnd = m_playPos[Mode_PlaySong].m_timeLine->loopEnd(); + } + + if (!m_exportLoop) + m_exportSongEnd += MidiTime(1,0); + + m_exportSongBegin = MidiTime(0,0); + m_exportLoopBegin = m_playPos[Mode_PlaySong].m_timeLine->loopBegin() < m_exportSongEnd && + m_playPos[Mode_PlaySong].m_timeLine->loopEnd() <= m_exportSongEnd ? + m_playPos[Mode_PlaySong].m_timeLine->loopBegin() : MidiTime(0,0); + m_exportLoopEnd = m_playPos[Mode_PlaySong].m_timeLine->loopBegin() < m_exportSongEnd && + m_playPos[Mode_PlaySong].m_timeLine->loopEnd() <= m_exportSongEnd ? + m_playPos[Mode_PlaySong].m_timeLine->loopEnd() : MidiTime(0,0); + m_playPos[Mode_PlaySong].setTicks( 0 ); } + m_exportEffectiveLength = (m_exportLoopBegin - m_exportSongBegin) + (m_exportLoopEnd - m_exportLoopBegin) + * m_loopRenderCount + (m_exportSongEnd - m_exportLoopEnd); + m_loopRenderRemaining = m_loopRenderCount; + playSong(); m_exporting = true; @@ -741,7 +807,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(); } @@ -755,7 +821,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(); } @@ -804,7 +870,7 @@ AutomationPattern * Song::tempoAutomationPattern() AutomatedValueMap Song::automatedValuesAt(MidiTime time, int tcoNum) const { - return TrackContainer::automatedValuesFromTracks(TrackList(tracks()) << m_globalAutomationTrack, time, tcoNum); + return TrackContainer::automatedValuesFromTracks(TrackList{m_globalAutomationTrack} << tracks(), time, tcoNum); } @@ -997,8 +1063,6 @@ void Song::loadProject( const QString & fileName ) clearErrors(); - DataFile::LocaleHelper localeHelper( DataFile::LocaleHelper::ModeLoad ); - Engine::mixer()->requestChangeInModel(); // get the header information from the DOM @@ -1115,6 +1179,11 @@ void Song::loadProject( const QString & fileName ) // now that everything is loaded ControllerConnection::finalizeConnections(); + // Remove dummy controllers that was added for correct connections + m_controllers.erase(std::remove_if(m_controllers.begin(), m_controllers.end(), + [](Controller* c){return c->type() == Controller::DummyController;}), + m_controllers.end()); + // resolve all IDs so that autoModels are automated AutomationPattern::resolveAllIDs(); @@ -1156,9 +1225,8 @@ void Song::loadProject( const QString & fileName ) // only save current song as _filename and do nothing else bool Song::saveProjectFile( const QString & filename ) { - DataFile::LocaleHelper localeHelper( DataFile::LocaleHelper::ModeSave ); - DataFile dataFile( DataFile::SongProject ); + m_savingProject = true; m_tempoModel.saveSettings( dataFile, dataFile.head(), "bpm" ); m_timeSigModel.saveSettings( dataFile, dataFile.head(), "timesig" ); @@ -1186,6 +1254,8 @@ bool Song::saveProjectFile( const QString & filename ) saveControllerStates( dataFile, dataFile.content() ); + m_savingProject = false; + return dataFile.writeFile( filename ); } @@ -1222,7 +1292,11 @@ bool Song::guiSaveProjectAs( const QString & _file_name ) m_oldFileName = m_fileName; setProjectFileName(_file_name); - if(!guiSaveProject()) + bool saveResult = guiSaveProject(); + // After saving as, restore default save options. + m_saveOptions.setDefaultOptions(); + + if(!saveResult) { // Saving failed. Restore old filenames. setProjectFileName(m_oldFileName); @@ -1259,9 +1333,13 @@ void Song::restoreControllerStates( const QDomElement & element ) while( !node.isNull() && !isCancelled() ) { Controller * c = Controller::create( node.toElement(), this ); - Q_ASSERT( c != NULL ); - - addController( c ); + if (c) {addController(c);} + else + { + // Fix indices to ensure correct connections + m_controllers.append(Controller::create( + Controller::DummyController, this)); + } node = node.nextSibling(); } @@ -1387,3 +1465,7 @@ QString Song::errorSummary() return errors; } + +bool Song::isSavingProject() const { + return m_savingProject; +} diff --git a/src/core/StepRecorder.cpp b/src/core/StepRecorder.cpp new file mode 100644 index 000000000..7a63e88e2 --- /dev/null +++ b/src/core/StepRecorder.cpp @@ -0,0 +1,366 @@ +/* + * 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. + * + */ + +#include "StepRecorder.h" +#include "StepRecorderWidget.h" +#include "PianoRoll.h" + +#include + +#include +using std::min; +using std::max; + +const int REMOVE_RELEASED_NOTE_TIME_THRESHOLD_MS = 70; + +StepRecorder::StepRecorder(PianoRoll& pianoRoll, StepRecorderWidget& stepRecorderWidget): + m_pianoRoll(pianoRoll), + m_stepRecorderWidget(stepRecorderWidget) +{ + m_stepRecorderWidget.hide(); +} + +void StepRecorder::initialize() +{ + connect(&m_updateReleasedTimer, SIGNAL(timeout()), this, SLOT(removeNotesReleasedForTooLong())); +} + +void StepRecorder::start(const MidiTime& currentPosition, const MidiTime& stepLength) +{ + m_isRecording = true; + + setStepsLength(stepLength); + + // quantize current position to get start recording position + const int q = m_pianoRoll.quantization(); + const int curPosTicks = currentPosition.getTicks(); + const int QuantizedPosTicks = (curPosTicks / q) * q; + const MidiTime& QuantizedPos = MidiTime(QuantizedPosTicks); + + m_curStepStartPos = QuantizedPos; + m_curStepLength = 0; + + m_stepRecorderWidget.show(); + + m_stepRecorderWidget.showHint(); + + prepareNewStep(); +} + +void StepRecorder::stop() +{ + m_stepRecorderWidget.hide(); + m_isRecording = false; +} + +void StepRecorder::notePressed(const Note & n) +{ + //if this is the first pressed note in step, advance position + if(!m_isStepInProgress) + { + m_isStepInProgress = true; + + //move curser one step forwards + stepForwards(); + } + + StepNote* stepNote = findCurStepNote(n.key()); + if(stepNote == nullptr) + { + m_curStepNotes.append(new StepNote(Note(m_curStepLength, m_curStepStartPos, n.key(), n.getVolume(), n.getPanning()))); + m_pianoRoll.update(); + } + else if (stepNote->isReleased()) + { + stepNote->setPressed(); + } +} + +void StepRecorder::noteReleased(const Note & n) +{ + StepNote* stepNote = findCurStepNote(n.key()); + + if(stepNote != nullptr && stepNote->isPressed()) + { + stepNote->setReleased(); + + //if m_updateReleasedTimer is not already active, activate it + //(when activated, the timer will re-set itself as long as there are released notes) + if(!m_updateReleasedTimer.isActive()) + { + m_updateReleasedTimer.start(REMOVE_RELEASED_NOTE_TIME_THRESHOLD_MS); + } + + //check if all note are released, apply notes to pattern(or dimiss if length is zero) and prepare to record next step + if(allCurStepNotesReleased()) + { + if(m_curStepLength > 0) + { + applyStep(); + } + else + { + dismissStep(); + } + } + } +} + +bool StepRecorder::keyPressEvent(QKeyEvent* ke) +{ + bool event_handled = false; + + switch(ke->key()) + { + case Qt::Key_Right: + { + if(!ke->isAutoRepeat()) + { + stepForwards(); + } + event_handled = true; + break; + } + + case Qt::Key_Left: + { + if(!ke->isAutoRepeat()) + { + stepBackwards(); + } + event_handled = true; + break; + } + } + + return event_handled; +} + +void StepRecorder::setStepsLength(const MidiTime& newLength) +{ + if(m_isStepInProgress) + { + //update current step length by the new amount : (number_of_steps * newLength) + m_curStepLength = (m_curStepLength / m_stepsLength) * newLength; + + updateCurStepNotes(); + } + + m_stepsLength = newLength; + + updateWidget(); +} + +QVector StepRecorder::getCurStepNotes() +{ + QVector notes; + + if(m_isStepInProgress) + { + for(StepNote* stepNote: m_curStepNotes) + { + notes.append(&stepNote->m_note); + } + } + + return notes; +} + +void StepRecorder::stepForwards() +{ + if(m_isStepInProgress) + { + m_curStepLength += m_stepsLength; + + updateCurStepNotes(); + } + else + { + m_curStepStartPos += m_stepsLength; + } + + updateWidget(); +} + +void StepRecorder::stepBackwards() +{ + if(m_isStepInProgress) + { + if(m_curStepLength > 0) + { + m_curStepLength = max(m_curStepLength - m_stepsLength, 0); + } + else + { + //if length is already zero - move starting position backwards + m_curStepStartPos = max(m_curStepStartPos - m_stepsLength, 0); + } + + updateCurStepNotes(); + } + else + { + m_curStepStartPos = max(m_curStepStartPos - m_stepsLength, 0); + } + + updateWidget(); +} + +void StepRecorder::applyStep() +{ + m_pattern->addJournalCheckPoint(); + + for (const StepNote* stepNote : m_curStepNotes) + { + m_pattern->addNote(stepNote->m_note, false); + } + + m_pattern->rearrangeAllNotes(); + m_pattern->updateLength(); + m_pattern->dataChanged(); + Engine::getSong()->setModified(); + + prepareNewStep(); +} + +void StepRecorder::dismissStep() +{ + if(!m_isStepInProgress) + { + return; + } + + prepareNewStep(); +} + +void StepRecorder::prepareNewStep() +{ + for(StepNote* stepNote : m_curStepNotes) + { + delete stepNote; + } + m_curStepNotes.clear(); + + m_isStepInProgress = false; + + m_curStepStartPos = getCurStepEndPos(); + m_curStepLength = 0; + + updateWidget(); +} + +void StepRecorder::setCurrentPattern( Pattern* newPattern ) +{ + if(m_pattern != NULL && m_pattern != newPattern) + { + dismissStep(); + } + + m_pattern = newPattern; +} + +void StepRecorder::removeNotesReleasedForTooLong() +{ + int nextTimout = std::numeric_limits::max(); + bool notesRemoved = false; + + QMutableVectorIterator itr(m_curStepNotes); + while (itr.hasNext()) + { + StepNote* stepNote = itr.next(); + + if(stepNote->isReleased()) + { + const int timeSinceReleased = stepNote->timeSinceReleased(); // capture value to avoid wraparound when calculting nextTimout + if (timeSinceReleased >= REMOVE_RELEASED_NOTE_TIME_THRESHOLD_MS) + { + delete stepNote; + itr.remove(); + notesRemoved = true; + } + else + { + nextTimout = min(nextTimout, REMOVE_RELEASED_NOTE_TIME_THRESHOLD_MS - timeSinceReleased); + } + } + } + + if(notesRemoved) + { + m_pianoRoll.update(); + } + + if(nextTimout != std::numeric_limits::max()) + { + m_updateReleasedTimer.start(nextTimout); + } + else + { + // no released note found for next timout, stop timer + m_updateReleasedTimer.stop(); + } +} + +MidiTime StepRecorder::getCurStepEndPos() +{ + return m_curStepStartPos + m_curStepLength; +} + +void StepRecorder::updateCurStepNotes() +{ + for (StepNote* stepNote : m_curStepNotes) + { + stepNote->m_note.setLength(m_curStepLength); + stepNote->m_note.setPos(m_curStepStartPos); + } +} + +void StepRecorder::updateWidget() +{ + m_stepRecorderWidget.setStartPosition(m_curStepStartPos); + m_stepRecorderWidget.setEndPosition(getCurStepEndPos()); + m_stepRecorderWidget.setStepsLength(m_stepsLength); +} + +bool StepRecorder::allCurStepNotesReleased() +{ + for (const StepNote* stepNote : m_curStepNotes) + { + if(stepNote->isPressed()) + { + return false; + } + } + + return true; +} + +StepRecorder::StepNote* StepRecorder::findCurStepNote(const int key) +{ + for (StepNote* stepNote : m_curStepNotes) + { + if(stepNote->m_note.key() == key) + { + return stepNote; + } + } + + return nullptr; +} diff --git a/src/core/TempoSyncKnobModel.cpp b/src/core/TempoSyncKnobModel.cpp index e94c6e424..a85ca2e9f 100644 --- a/src/core/TempoSyncKnobModel.cpp +++ b/src/core/TempoSyncKnobModel.cpp @@ -42,7 +42,8 @@ TempoSyncKnobModel::TempoSyncKnobModel( const float _val, const float _min, m_custom( _parent ) { connect( Engine::getSong(), SIGNAL( tempoChanged( bpm_t ) ), - this, SLOT( calculateTempoSyncTime( bpm_t ) ) ); + this, SLOT( calculateTempoSyncTime( bpm_t ) ), + Qt::DirectConnection ); } @@ -154,7 +155,8 @@ void TempoSyncKnobModel::setSyncMode( TempoSyncMode _new_mode ) if( _new_mode == SyncCustom ) { connect( &m_custom, SIGNAL( dataChanged() ), - this, SLOT( updateCustom() ) ); + this, SLOT( updateCustom() ), + Qt::DirectConnection ); } } calculateTempoSyncTime( Engine::getSong()->getTempo() ); diff --git a/src/core/Track.cpp b/src/core/Track.cpp index 5c9d38499..30920823a 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. * @@ -95,7 +99,6 @@ TextFloat * TrackContentObjectView::s_textFloat = NULL; TrackContentObject::TrackContentObject( Track * track ) : Model( track ), m_track( track ), - m_name( QString::null ), m_startPosition(), m_length(), m_mutedModel( false, this, tr( "Mute" ) ), @@ -268,6 +271,9 @@ TrackContentObjectView::TrackContentObjectView( TrackContentObject * tco, m_action( NoAction ), m_initialMousePos( QPoint( 0, 0 ) ), m_initialMouseGlobalPos( QPoint( 0, 0 ) ), + m_initialTCOPos( MidiTime(0) ), + m_initialTCOEnd( MidiTime(0) ), + m_initialOffsets( QVector() ), m_hint( NULL ), m_mutedColor( 0, 0, 0 ), m_mutedBackgroundColor( 0, 0, 0 ), @@ -329,8 +335,8 @@ TrackContentObjectView::~TrackContentObjectView() /*! \brief Update a TrackContentObjectView * - * TCO's get drawn only when needed, - * and when a TCO is updated, + * TCO's get drawn only when needed, + * and when a TCO is updated, * it needs to be redrawn. * */ @@ -487,8 +493,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(); @@ -525,8 +531,9 @@ void TrackContentObjectView::updatePosition() void TrackContentObjectView::dragEnterEvent( QDragEnterEvent * dee ) { TrackContentWidget * tcw = getTrackView()->getTrackContentWidget(); - MidiTime tcoPos = MidiTime( m_tco->startPosition().getTact(), 0 ); - if( tcw->canPasteSelection( tcoPos, dee->mimeData() ) == false ) + MidiTime tcoPos = MidiTime( m_tco->startPosition() ); + + if( tcw->canPasteSelection( tcoPos, dee ) == false ) { dee->ignore(); } @@ -564,7 +571,8 @@ void TrackContentObjectView::dropEvent( QDropEvent * de ) if( m_trackView->trackContainerView()->allowRubberband() == true ) { TrackContentWidget * tcw = getTrackView()->getTrackContentWidget(); - MidiTime tcoPos = MidiTime( m_tco->startPosition().getTact(), 0 ); + MidiTime tcoPos = MidiTime( m_tco->startPosition() ); + if( tcw->pasteSelection( tcoPos, de ) == true ) { de->accept(); @@ -599,9 +607,9 @@ void TrackContentObjectView::dropEvent( QDropEvent * de ) */ void TrackContentObjectView::leaveEvent( QEvent * e ) { - while( QApplication::overrideCursor() != NULL ) + if( cursor().shape() != Qt::BitmapCursor ) { - QApplication::restoreOverrideCursor(); + setCursor( QCursor( embed::getIconPixmap( "hand" ), 3, 3 ) ); } if( e != NULL ) { @@ -631,9 +639,12 @@ DataFile TrackContentObjectView::createTCODataFiles( it != tcoViews.end(); ++it ) { // Insert into the dom under the "tcos" element - int trackIndex = tc->tracks().indexOf( ( *it )->m_trackView->getTrack() ); + Track* tcoTrack = ( *it )->m_trackView->getTrack(); + int trackIndex = tc->tracks().indexOf( tcoTrack ); QDomElement tcoElement = dataFile.createElement( "tco" ); tcoElement.setAttribute( "trackIndex", trackIndex ); + tcoElement.setAttribute( "trackType", tcoTrack->type() ); + tcoElement.setAttribute( "trackName", tcoTrack->name() ); ( *it )->m_tco->saveState( dataFile, tcoElement ); tcoParent.appendChild( tcoElement ); } @@ -650,7 +661,8 @@ DataFile TrackContentObjectView::createTCODataFiles( QDomElement metadata = dataFile.createElement( "copyMetadata" ); // initialTrackIndex is the index of the track that was touched metadata.setAttribute( "initialTrackIndex", initialTrackIndex ); - // grabbedTCOPos is the pos of the tact containing the TCO we grabbed + metadata.setAttribute( "trackContainerId", tc->id() ); + // grabbedTCOPos is the pos of the bar containing the TCO we grabbed metadata.setAttribute( "grabbedTCOPos", m_tco->startPosition() ); dataFile.content().appendChild( metadata ); @@ -708,7 +720,8 @@ void TrackContentObjectView::paintTextLabel(QString const & text, QPainter & pai */ void TrackContentObjectView::mousePressEvent( QMouseEvent * me ) { - setInitialMousePos( me->pos() ); + setInitialPos( me->pos() ); + setInitialOffsets(); if( !fixedTCOs() && me->button() == Qt::LeftButton ) { if( me->modifiers() & Qt::ControlModifier ) @@ -722,7 +735,9 @@ void TrackContentObjectView::mousePressEvent( QMouseEvent * me ) m_action = ToggleSelected; } } - else if( !me->modifiers() ) + else if( !me->modifiers() + || (me->modifiers() & Qt::AltModifier) + || (me->modifiers() & Qt::ShiftModifier) ) { if( isSelected() ) { @@ -736,50 +751,48 @@ void TrackContentObjectView::mousePressEvent( QMouseEvent * me ) // move or resize m_tco->setJournalling( false ); - setInitialMousePos( me->pos() ); + setInitialPos( me->pos() ); + setInitialOffsets(); SampleTCO * sTco = dynamic_cast( m_tco ); if( me->x() < RESIZE_GRIP_WIDTH && sTco && !m_tco->getAutoResize() ) { m_action = ResizeLeft; - QCursor c( Qt::SizeHorCursor ); - QApplication::setOverrideCursor( c ); + setCursor( Qt::SizeHorCursor ); } else if( me->x() < width() - RESIZE_GRIP_WIDTH ) { m_action = Move; - QCursor c( Qt::SizeAllCursor ); - QApplication::setOverrideCursor( c ); + setCursor( Qt::SizeAllCursor ); } else if( !m_tco->getAutoResize() ) { m_action = Resize; - QCursor c( Qt::SizeHorCursor ); - QApplication::setOverrideCursor( c ); + setCursor( Qt::SizeHorCursor ); } if( m_action == Move ) { 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 @@ -791,12 +804,7 @@ void TrackContentObjectView::mousePressEvent( QMouseEvent * me ) QString hint = m_action == Move || m_action == MoveSelection ? tr( "Press <%1> and drag to make a copy." ) : tr( "Press <%1> for free resizing." ); - m_hint = TextFloat::displayMessage( tr( "Hint" ), hint.arg( - #ifdef LMMS_BUILD_APPLE - "⌘"), - #else - "Ctrl"), - #endif + m_hint = TextFloat::displayMessage( tr( "Hint" ), hint.arg(UI_CTRL_KEY), embed::getIconPixmap( "hint" ), 0 ); } } @@ -875,7 +883,7 @@ void TrackContentObjectView::mouseMoveEvent( QMouseEvent * me ) DataFile dataFile = createTCODataFiles( tcoViews ); // TODO -- thumbnail for all selected - QPixmap thumbnail = QPixmap::grabWidget( this ).scaled( + QPixmap thumbnail = grab().scaled( 128, 128, Qt::KeepAspectRatio, Qt::SmoothTransformation ); @@ -891,76 +899,89 @@ 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 ) { - 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 ) ); - if( ! ( me->modifiers() & Qt::ControlModifier ) - && me->button() == Qt::NoButton ) - { - t = t.toNearestTact(); - } - m_tco->movePosition( t ); + MidiTime newPos = draggedTCOPos( me ); + + // Don't go left of bar zero + newPos = max( 0, newPos.getTicks() ); + m_tco->movePosition( newPos ); m_trackView->getTrackContentWidget()->changePosition(); s_textFloat->setText( QString( "%1:%2" ). - arg( m_tco->startPosition().getTact() + 1 ). - arg( m_tco->startPosition().getTicks() % - MidiTime::ticksPerTact() ) ); + arg( newPos.getBar() + 1 ). + arg( newPos.getTicks() % + MidiTime::ticksPerBar() ) ); s_textFloat->moveGlobal( this, QPoint( width() + 2, height() + 2 ) ); } else if( m_action == MoveSelection ) { - const int dx = me->x() - m_initialMousePos.x(); + // 1: Find the position we want to move the grabbed TCO to + MidiTime newPos = draggedTCOPos( me ); + + // 2: Handle moving the other selected TCOs the same distance QVector so = m_trackView->trackContainerView()->selectedObjects(); - QVector tcos; - MidiTime smallest_pos, t; - // find out smallest position of all selected objects for not - // moving an object before zero + QVector tcos; // List of selected clips + int leftmost = 0; // Leftmost clip's offset from grabbed clip + // Populate tcos, find leftmost for( QVector::iterator it = so.begin(); it != so.end(); ++it ) { TrackContentObjectView * tcov = dynamic_cast( *it ); - if( tcov == NULL ) - { - continue; - } - TrackContentObject * tco = tcov->m_tco; - tcos.push_back( tco ); - smallest_pos = qMin( smallest_pos, - (int)tco->startPosition() + - static_cast( dx * - MidiTime::ticksPerTact() / ppt ) ); + if( tcov == NULL ) { continue; } + tcos.push_back( tcov->m_tco ); + int index = std::distance( so.begin(), it ); + leftmost = min (leftmost, m_initialOffsets[index].getTicks() ); } + // Make sure the leftmost clip doesn't get moved to a negative position + if ( newPos.getTicks() + leftmost < 0 ) { newPos = -leftmost; } + for( QVector::iterator it = tcos.begin(); it != tcos.end(); ++it ) { - t = ( *it )->startPosition() + - static_cast( dx *MidiTime::ticksPerTact() / - ppt )-smallest_pos; - if( ! ( me->modifiers() & Qt::ControlModifier ) - && me->button() == Qt::NoButton ) - { - t = t.toNearestTact(); - } - ( *it )->movePosition( t ); + int index = std::distance( tcos.begin(), it ); + ( *it )->movePosition( newPos + m_initialOffsets[index] ); } } else if( m_action == Resize || m_action == ResizeLeft ) { + // If the user is holding alt, or pressed ctrl after beginning the drag, don't quantize + 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::ticksPerBar()) ); + if( m_action == Resize ) { - MidiTime t = qMax( MidiTime::ticksPerTact() / 16, static_cast( me->x() * MidiTime::ticksPerTact() / ppt ) ); - if( ! ( me->modifiers() & Qt::ControlModifier ) && me->button() == Qt::NoButton ) - { - t = qMax( MidiTime::ticksPerTact(), t.toNearestTact() ); + // The clip's new length + MidiTime l = static_cast( me->x() * MidiTime::ticksPerBar() / ppb ); + + if ( unquantized ) + { // We want to preserve this adjusted offset, + // even if the user switches to snapping later + setInitialPos( m_initialMousePos ); + // Don't resize to less than 1 tick + m_tco->changeLength( qMax( 1, l ) ); + } + else if ( me->modifiers() & Qt::ShiftModifier ) + { // If shift is held, quantize clip's end position + MidiTime end = MidiTime( m_initialTCOPos + l ).quantize( snapSize ); + // The end position has to be after the clip's start + MidiTime min = m_initialTCOPos.quantize( snapSize ); + if ( min <= m_initialTCOPos ) min += snapLength; + m_tco->changeLength( qMax(min - m_initialTCOPos, end - m_initialTCOPos) ); + } + else + { // Otherwise, resize in fixed increments + MidiTime initialLength = m_initialTCOEnd - m_initialTCOPos; + MidiTime offset = MidiTime( l - initialLength ).quantize( snapSize ); + // Don't resize to less than 1 tick + MidiTime min = MidiTime( initialLength % snapLength ); + if (min < 1) min += snapLength; + m_tco->changeLength( qMax( min, initialLength + offset) ); } - m_tco->changeLength( t ); } else { @@ -970,16 +991,35 @@ 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 ) ); - if( ! ( me->modifiers() & Qt::ControlModifier ) - && me->button() == Qt::NoButton ) - { - t = t.toNearestTact(); + m_trackView->trackContainerView()->currentPosition() + + static_cast( x * MidiTime::ticksPerBar() / ppb ) ); + + if( unquantized ) + { // We want to preserve this adjusted offset, + // even if the user switches to snapping later + setInitialPos( m_initialMousePos ); + //Don't resize to less than 1 tick + t = qMin( m_initialTCOEnd - 1, t); } + else if( me->modifiers() & Qt::ShiftModifier ) + { // If shift is held, quantize clip's start position + // Don't let the start position move past the end position + MidiTime max = m_initialTCOEnd.quantize( snapSize ); + if ( max >= m_initialTCOEnd ) max -= snapLength; + t = qMin( max, t.quantize( snapSize ) ); + } + else + { // Otherwise, resize in fixed increments + // Don't resize to less than 1 tick + MidiTime initialLength = m_initialTCOEnd - m_initialTCOPos; + MidiTime minLength = MidiTime( initialLength % snapLength ); + if (minLength < 1) minLength += snapLength; + MidiTime offset = MidiTime(t - m_initialTCOPos).quantize( snapSize ); + t = qMin( m_initialTCOEnd - minLength, m_initialTCOPos + offset ); + } + MidiTime oldPos = m_tco->startPosition(); - if( m_tco->length() + ( oldPos - t ) >= MidiTime::ticksPerTact() ) + if( m_tco->length() + ( oldPos - t ) >= 1 ) { m_tco->movePosition( t ); m_trackView->getTrackContentWidget()->changePosition(); @@ -989,15 +1029,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 @@ -1006,17 +1046,7 @@ void TrackContentObjectView::mouseMoveEvent( QMouseEvent * me ) if( ( me->x() > width() - RESIZE_GRIP_WIDTH && !me->buttons() && !m_tco->getAutoResize() ) || ( me->x() < RESIZE_GRIP_WIDTH && !me->buttons() && sTco && !m_tco->getAutoResize() ) ) { - if( QApplication::overrideCursor() != NULL && - QApplication::overrideCursor()->shape() != - Qt::SizeHorCursor ) - { - while( QApplication::overrideCursor() != NULL ) - { - QApplication::restoreOverrideCursor(); - } - } - QCursor c( Qt::SizeHorCursor ); - QApplication::setOverrideCursor( c ); + setCursor( Qt::SizeHorCursor ); } else { @@ -1093,12 +1123,7 @@ void TrackContentObjectView::contextMenuEvent( QContextMenuEvent * cme ) tr( "Paste" ), m_tco, SLOT( paste() ) ); contextMenu.addSeparator(); contextMenu.addAction( embed::getIconPixmap( "muted" ), - tr( "Mute/unmute (<%1> + middle click)" ).arg( - #ifdef LMMS_BUILD_APPLE - "⌘"), - #else - "Ctrl"), - #endif + tr( "Mute/unmute (<%1> + middle click)" ).arg(UI_CTRL_KEY), m_tco, SLOT( toggleMute() ) ); constructContextMenu( &contextMenu ); @@ -1108,14 +1133,34 @@ 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(); +} + + +/*! \brief Save the offsets between all selected tracks and a clicked track */ +void TrackContentObjectView::setInitialOffsets() +{ + QVector so = m_trackView->trackContainerView()->selectedObjects(); + QVector offsets; + for( QVector::iterator it = so.begin(); + it != so.end(); ++it ) + { + TrackContentObjectView * tcov = + dynamic_cast( *it ); + if( tcov == NULL ) + { + continue; + } + offsets.push_back( tcov->m_tco->startPosition() - m_initialTCOPos ); + } + + m_initialOffsets = offsets; } @@ -1135,6 +1180,49 @@ bool TrackContentObjectView::mouseMovedDistance( QMouseEvent * me, int distance +/*! \brief Calculate the new position of a dragged TCO from a mouse event + * + * + * \param me The QMouseEvent + */ +MidiTime TrackContentObjectView::draggedTCOPos( QMouseEvent * me ) +{ + //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::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 + || (me->modifiers() & Qt::ControlModifier) + || (me->modifiers() & Qt::AltModifier) ) + { + // We want to preserve this adjusted offset, + // even if the user switches to snapping + setInitialPos( m_initialMousePos ); + } + else if ( me->modifiers() & Qt::ShiftModifier ) + { // If shift is held, quantize position (Default in 1.2.0 and earlier) + // or end position, whichever is closest to the actual position + MidiTime startQ = newPos.quantize( gui->songEditor()->m_editor->getSnapSize() ); + // Find start position that gives snapped clip end position + MidiTime endQ = ( newPos + m_tco->length() ); + endQ = endQ.quantize( gui->songEditor()->m_editor->getSnapSize() ); + endQ = endQ - m_tco->length(); + // Select the position closest to actual position + if ( abs(newPos - startQ) < abs(newPos - endQ) ) newPos = startQ; + else newPos = endQ; + } + else + { // Otherwise, quantize moved distance (preserves user offsets) + newPos = m_initialTCOPos + offset.quantize( gui->songEditor()->m_editor->getSnapSize() ); + } + return newPos; +} + + + // =========================================================================== // trackContentWidget @@ -1182,13 +1270,12 @@ 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; + int w = ppb * BARS_PER_GROUP; int h = height(); m_background = QPixmap( w * 2, height() ); QPainter pmp( &m_background ); @@ -1198,20 +1285,20 @@ void TrackContentWidget::updateBackground() // draw lines // vertical lines - pmp.setPen( QPen( gridColor(), 1 ) ); - for( float x = 0; x < w * 2; x += ppt ) + pmp.setPen( QPen( gridColor(), 1 ) ); + 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 ) ); } - + // horizontal line - pmp.setPen( QPen( gridColor(), 1 ) ); + pmp.setPen( QPen( gridColor(), 1 ) ); pmp.drawLine( 0, h-1, w*2, h-1 ); pmp.end(); @@ -1252,7 +1339,7 @@ void TrackContentWidget::addTCOView( TrackContentObjectView * tcov ) */ void TrackContentWidget::removeTCOView( TrackContentObjectView * tcov ) { - tcoViewVector::iterator it = qFind( m_tcoViews.begin(), + tcoViewVector::iterator it = std::find( m_tcoViews.begin(), m_tcoViews.end(), tcov ); if( it != m_tcoViews.end() ) @@ -1300,7 +1387,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(); @@ -1316,7 +1403,7 @@ void TrackContentWidget::changePosition( const MidiTime & newPos ) it != m_tcoViews.end(); ++it ) { if( ( *it )->getTrackContentObject()-> - startPosition().getTact() != curBB ) + startPosition().getBar() != curBB ) { ( *it )->hide(); } @@ -1333,7 +1420,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(); @@ -1350,8 +1437,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() ) { @@ -1372,7 +1459,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. */ @@ -1381,8 +1468,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() ) ); } @@ -1394,8 +1481,8 @@ MidiTime TrackContentWidget::getPosition( int mouseX ) */ void TrackContentWidget::dragEnterEvent( QDragEnterEvent * dee ) { - MidiTime tcoPos = MidiTime( getPosition( dee->pos().x() ).getTact(), 0 ); - if( canPasteSelection( tcoPos, dee->mimeData() ) == false ) + MidiTime tcoPos = getPosition( dee->pos().x() ); + if( canPasteSelection( tcoPos, dee ) == false ) { dee->ignore(); } @@ -1414,8 +1501,10 @@ void TrackContentWidget::dragEnterEvent( QDragEnterEvent * dee ) * \param tcoPos the position of the TCO slot being pasted on * \param de the DropEvent generated */ -bool TrackContentWidget::canPasteSelection( MidiTime tcoPos, const QMimeData * mimeData ) +bool TrackContentWidget::canPasteSelection( MidiTime tcoPos, const QDropEvent* de ) { + const QMimeData * mimeData = de->mimeData(); + Track * t = getTrack(); QString type = StringPairDrag::decodeMimeKey( mimeData ); QString value = StringPairDrag::decodeMimeValue( mimeData ); @@ -1434,7 +1523,7 @@ bool TrackContentWidget::canPasteSelection( MidiTime tcoPos, const QMimeData * m 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" ); @@ -1444,8 +1533,10 @@ bool TrackContentWidget::canPasteSelection( MidiTime tcoPos, const QMimeData * m const TrackContainer::TrackList tracks = t->trackContainer()->tracks(); const int currentTrackIndex = tracks.indexOf( t ); - // Don't paste if we're on the same tact - if( tcoPos == grabbedTCOTact && currentTrackIndex == initialTrackIndex ) + // 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 == grabbedTCOBar && currentTrackIndex == initialTrackIndex ) { return false; } @@ -1468,9 +1559,9 @@ bool TrackContentWidget::canPasteSelection( MidiTime tcoPos, const QMimeData * m } // Track must be of the same type - Track * startTrack = tracks.at( trackIndex ); + auto startTrackType = tcoElement.attributeNode("trackType").value().toInt(); Track * endTrack = tracks.at( finalTrackIndex ); - if( startTrack->type() != endTrack->type() ) + if( startTrackType != endTrack->type() ) { return false; } @@ -1486,7 +1577,7 @@ bool TrackContentWidget::canPasteSelection( MidiTime tcoPos, const QMimeData * m */ bool TrackContentWidget::pasteSelection( MidiTime tcoPos, QDropEvent * de ) { - if( canPasteSelection( tcoPos, de->mimeData() ) == false ) + if( canPasteSelection( tcoPos, de ) == false ) { return false; } @@ -1509,9 +1600,8 @@ bool TrackContentWidget::pasteSelection( MidiTime tcoPos, QDropEvent * de ) int initialTrackIndex = tiAttr.value().toInt(); QDomAttr tcoPosAttr = metadata.attributeNode( "grabbedTCOPos" ); MidiTime grabbedTCOPos = tcoPosAttr.value().toInt(); - MidiTime grabbedTCOTact = MidiTime( grabbedTCOPos.getTact(), 0 ); - // 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() ); @@ -1530,6 +1620,10 @@ bool TrackContentWidget::pasteSelection( MidiTime tcoPos, QDropEvent * de ) // TODO -- Need to draw the hovericon either way, or ghost the TCOs // onto their final position. + // All patterns should be offset the same amount as the grabbed pattern + // The offset is quantized (rather than the positions) to preserve fine adjustments + int offset = MidiTime(tcoPos - grabbedTCOPos).quantize(gui->songEditor()->m_editor->getSnapSize()); + for( int i = 0; isongEditor()->m_editor->getSnapSize(); + if (offset == 0) { pos += shift; } TrackContentObject * tco = t->createTCO( pos ); tco->restoreState( tcoElement ); @@ -1556,7 +1648,8 @@ bool TrackContentWidget::pasteSelection( MidiTime tcoPos, QDropEvent * de ) } //check tco name, if the same as source track name dont copy - if( tco->name() == tracks[trackIndex]->name() ) + QString sourceTrackName = outerTCOElement.attributeNode( "trackName" ).value(); + if( tco->name() == sourceTrackName ) { tco->setName( "" ); } @@ -1574,7 +1667,7 @@ bool TrackContentWidget::pasteSelection( MidiTime tcoPos, QDropEvent * de ) */ void TrackContentWidget::dropEvent( QDropEvent * de ) { - MidiTime tcoPos = MidiTime( getPosition( de->pos().x() ).getTact(), 0 ); + MidiTime tcoPos = MidiTime( getPosition( de->pos().x() ) ); if( pasteSelection( tcoPos, de ) == true ) { de->accept(); @@ -1607,8 +1700,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 ); @@ -1626,15 +1719,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 ) ); } } @@ -1667,15 +1760,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 ); } @@ -1734,12 +1827,7 @@ TrackOperationsWidget::TrackOperationsWidget( TrackView * parent ) : m_trackView( parent ) /*!< The parent track view */ { ToolTip::add( this, tr( "Press <%1> while clicking on move-grip " - "to begin a new drag'n'drop action." ).arg( - #ifdef LMMS_BUILD_APPLE - "⌘") ); - #else - "Ctrl") ); - #endif + "to begin a new drag'n'drop action." ).arg(UI_CTRL_KEY) ); QMenu * toMenu = new QMenu( this ); toMenu->setFont( pointSize<9>( toMenu->font() ) ); @@ -1823,8 +1911,7 @@ void TrackOperationsWidget::mousePressEvent( QMouseEvent * me ) m_trackView->getTrack()->saveState( dataFile, dataFile.content() ); new StringPairDrag( QString( "track_%1" ).arg( m_trackView->getTrack()->type() ), - dataFile.toString(), QPixmap::grabWidget( - m_trackView->getTrackSettingsWidget() ), + dataFile.toString(), m_trackView->getTrackSettingsWidget()->grab(), this ); } else if( me->button() == Qt::LeftButton ) @@ -1896,6 +1983,7 @@ void TrackOperationsWidget::cloneTrack() void TrackOperationsWidget::clearTrack() { Track * t = m_trackView->getTrack(); + t->addJournalCheckPoint(); t->lock(); t->deleteTCOs(); t->unlock(); @@ -1929,17 +2017,20 @@ void TrackOperationsWidget::updateMenu() toMenu->addAction( embed::getIconPixmap( "cancel", 16, 16 ), tr( "Remove this track" ), this, SLOT( removeTrack() ) ); - + if( ! m_trackView->trackContainerView()->fixedTCOs() ) { toMenu->addAction( tr( "Clear this track" ), this, SLOT( clearTrack() ) ); } - if( InstrumentTrackView * trackView = dynamic_cast( m_trackView ) ) + if (QMenu *fxMenu = m_trackView->createFxMenu(tr("FX %1: %2"), tr("Assign to new FX Channel"))) { - QMenu *fxMenu = trackView->createFxMenu( tr( "FX %1: %2" ), tr( "Assign to new FX Channel" )); toMenu->addMenu(fxMenu); + } + + if (InstrumentTrackView * trackView = dynamic_cast(m_trackView)) + { toMenu->addSeparator(); - toMenu->addMenu( trackView->midiMenu() ); + toMenu->addMenu(trackView->midiMenu()); } if( dynamic_cast( m_trackView ) ) { @@ -2137,8 +2228,9 @@ void Track::saveSettings( QDomDocument & doc, QDomElement & element ) } element.setAttribute( "type", type() ); element.setAttribute( "name", name() ); - element.setAttribute( "muted", isMuted() ); - element.setAttribute( "solo", isSolo() ); + m_mutedModel.saveSettings( doc, element, "muted" ); + m_soloModel.saveSettings( doc, element, "solo" ); + if( m_height >= MINIMAL_TRACK_HEIGHT ) { element.setAttribute( "trackheight", m_height ); @@ -2190,8 +2282,8 @@ void Track::loadSettings( const QDomElement & element ) setName( element.hasAttribute( "name" ) ? element.attribute( "name" ) : element.firstChild().toElement().attribute( "name" ) ); - setMuted( element.attribute( "muted" ).toInt() ); - setSolo( element.attribute( "solo" ).toInt() ); + m_mutedModel.loadSettings( element, "muted" ); + m_soloModel.loadSettings( element, "solo" ); if( m_simpleSerializingMode ) { @@ -2224,8 +2316,9 @@ void Track::loadSettings( const QDomElement & element ) { loadTrackSpecificSettings( node.toElement() ); } - else if( - !node.toElement().attribute( "metadata" ).toInt() ) + else if( node.nodeName() != "muted" + && node.nodeName() != "solo" + && !node.toElement().attribute( "metadata" ).toInt() ) { TrackContentObject * tco = createTCO( MidiTime( 0 ) ); @@ -2269,7 +2362,7 @@ TrackContentObject * Track::addTCO( TrackContentObject * tco ) */ void Track::removeTCO( TrackContentObject * tco ) { - tcoVector::iterator it = qFind( m_trackContentObjects.begin(), + tcoVector::iterator it = std::find( m_trackContentObjects.begin(), m_trackContentObjects.end(), tco ); if( it != m_trackContentObjects.end() ) @@ -2326,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() ); } @@ -2341,7 +2434,7 @@ TrackContentObject * Track::getTCO( int tcoNum ) int Track::getTCONum( const TrackContentObject * tco ) { // for( int i = 0; i < getTrackContentWidget()->numOfTCOs(); ++i ) - tcoVector::iterator it = qFind( m_trackContentObjects.begin(), + tcoVector::iterator it = std::find( m_trackContentObjects.begin(), m_trackContentObjects.end(), tco ); if( it != m_trackContentObjects.end() ) @@ -2434,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() ); } } } @@ -2456,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 ) ); } } } @@ -2480,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; @@ -2500,7 +2593,7 @@ tact_t Track::length() const } } - return last / MidiTime::ticksPerTact(); + return last / MidiTime::ticksPerBar(); } @@ -2620,7 +2713,7 @@ TrackView::TrackView( Track * track, TrackContainerView * tcv ) : &m_trackContentWidget, SLOT( update() ) ); connect( &m_track->m_soloModel, SIGNAL( dataChanged() ), - m_track, SLOT( toggleSolo() ) ); + m_track, SLOT( toggleSolo() ), Qt::DirectConnection ); // create views for already existing TCOs for( Track::tcoVector::iterator it = m_track->m_trackContentObjects.begin(); @@ -2684,6 +2777,19 @@ void TrackView::update() +/*! \brief Create a menu for assigning/creating channels for this track. + * + */ +QMenu * TrackView::createFxMenu(QString title, QString newFxLabel) +{ + Q_UNUSED(title) + Q_UNUSED(newFxLabel) + return NULL; +} + + + + /*! \brief Close this track View. * */ @@ -2854,12 +2960,12 @@ void TrackView::mouseMoveEvent( QMouseEvent * me ) else if( m_action == MoveTrack ) { // look which track-widget the mouse-cursor is over - const int yPos = + const int yPos = m_trackContainerView->contentWidget()->mapFromGlobal( me->globalPos() ).y(); const TrackView * trackAtY = m_trackContainerView->trackViewAt( yPos ); -// debug code -// qDebug( "y position %d", yPos ); + // debug code + // qDebug( "y position %d", yPos ); // a track-widget not equal to ourself? if( trackAtY != NULL && trackAtY != this ) 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/VstSyncController.cpp b/src/core/VstSyncController.cpp index b441d0507..dd9660cb5 100644 --- a/src/core/VstSyncController.cpp +++ b/src/core/VstSyncController.cpp @@ -136,12 +136,12 @@ VstSyncController::~VstSyncController() -void VstSyncController::setAbsolutePosition( int ticks ) +void VstSyncController::setAbsolutePosition( double ticks ) { #ifdef VST_SNC_LATENCY - m_syncData->ppqPos = ( ( ticks + 0 ) / (float)48 ) - m_syncData->m_latency; + m_syncData->ppqPos = ( ( ticks + 0 ) / 48.0 ) - m_syncData->m_latency; #else - m_syncData->ppqPos = ( ( ticks + 0 ) / (float)48 ); + m_syncData->ppqPos = ( ( ticks + 0 ) / 48.0 ); #endif } diff --git a/src/core/audio/AudioAlsa.cpp b/src/core/audio/AudioAlsa.cpp index 45abe6776..b86675706 100644 --- a/src/core/audio/AudioAlsa.cpp +++ b/src/core/audio/AudioAlsa.cpp @@ -37,10 +37,10 @@ AudioAlsa::AudioAlsa( bool & _success_ful, Mixer* _mixer ) : - AudioDevice( tLimit( + AudioDevice( qBound( + DEFAULT_CHANNELS, ConfigManager::inst()->value( "audioalsa", "channels" ).toInt(), - DEFAULT_CHANNELS, SURROUND_CHANNELS ), - _mixer ), + SURROUND_CHANNELS ), _mixer ), m_handle( NULL ), m_hwParams( NULL ), m_swParams( NULL ), diff --git a/src/core/audio/AudioFileMP3.cpp b/src/core/audio/AudioFileMP3.cpp index cce7ec8e4..a00cdf611 100644 --- a/src/core/audio/AudioFileMP3.cpp +++ b/src/core/audio/AudioFileMP3.cpp @@ -120,6 +120,7 @@ bool AudioFileMP3::initEncoder() lame_set_brate(m_lame, bitRate); // Add a comment + id3tag_init(m_lame); id3tag_set_comment(m_lame, "Created with LMMS"); return lame_init_params(m_lame) != -1; diff --git a/src/core/audio/AudioFileWave.cpp b/src/core/audio/AudioFileWave.cpp index 45e46b838..8a590a8b8 100644 --- a/src/core/audio/AudioFileWave.cpp +++ b/src/core/audio/AudioFileWave.cpp @@ -27,6 +27,9 @@ #include "endian_handling.h" #include "Mixer.h" +#include +#include + AudioFileWave::AudioFileWave( OutputSettings const & outputSettings, const ch_cnt_t channels, bool & successful, @@ -72,13 +75,15 @@ bool AudioFileWave::startEncoding() m_si.format |= SF_FORMAT_PCM_16; break; } - m_sf = sf_open( -#ifdef LMMS_BUILD_WIN32 - outputFile().toLocal8Bit().constData(), -#else - outputFile().toUtf8().constData(), -#endif - SFM_WRITE, &m_si ); + + // Use file handle to handle unicode file name on Windows + m_sf = sf_open_fd( outputFileHandle(), SFM_WRITE, &m_si, false ); + + if (!m_sf) + { + qWarning("Error: AudioFileWave::startEncoding: %s", sf_strerror(nullptr)); + return false; + } // Prevent fold overs when encountering clipped data sf_command(m_sf, SFC_SET_CLIPPING, NULL, SF_TRUE); diff --git a/src/core/audio/AudioJack.cpp b/src/core/audio/AudioJack.cpp index 4d730eed4..aebfe5e1c 100644 --- a/src/core/audio/AudioJack.cpp +++ b/src/core/audio/AudioJack.cpp @@ -32,7 +32,6 @@ #include "Engine.h" #include "GuiApplication.h" -#include "templates.h" #include "gui_templates.h" #include "ConfigManager.h" #include "LcdSpinBox.h" @@ -44,10 +43,10 @@ AudioJack::AudioJack( bool & _success_ful, Mixer* _mixer ) : - AudioDevice( tLimit( ConfigManager::inst()->value( - "audiojack", "channels" ).toInt(), - DEFAULT_CHANNELS, SURROUND_CHANNELS ), - _mixer ), + AudioDevice( qBound( + DEFAULT_CHANNELS, + ConfigManager::inst()->value( "audiojack", "channels" ).toInt(), + SURROUND_CHANNELS ), _mixer ), m_client( NULL ), m_active( false ), m_midiClient( NULL ), @@ -201,7 +200,6 @@ bool AudioJack::initJackClient() void AudioJack::startProcessing() { - QMutexLocker m( &m_processingMutex ); m_stopped = false; if( m_active || m_client == NULL ) @@ -254,7 +252,6 @@ void AudioJack::startProcessing() void AudioJack::stopProcessing() { - QMutexLocker m( &m_processingMutex ); m_stopped = true; } @@ -342,7 +339,6 @@ void AudioJack::renamePort( AudioPort * _port ) int AudioJack::processCallback( jack_nframes_t _nframes, void * _udata ) { - QMutexLocker m( &m_processingMutex ); // do midi processing first so that midi input can // add to the following sound processing @@ -406,6 +402,7 @@ int AudioJack::processCallback( jack_nframes_t _nframes, void * _udata ) m_framesDoneInCurBuf = 0; if( !m_framesToDoInCurBuf ) { + m_stopped = true; break; } } @@ -457,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 ); @@ -469,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 21f495dca..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" @@ -69,10 +69,10 @@ AudioOss::AudioOss( bool & _success_ful, Mixer* _mixer ) : - AudioDevice( tLimit( + AudioDevice( qBound( + DEFAULT_CHANNELS, ConfigManager::inst()->value( "audiooss", "channels" ).toInt(), - DEFAULT_CHANNELS, SURROUND_CHANNELS ), - _mixer ), + SURROUND_CHANNELS ), _mixer ), m_convertEndian( false ) { _success_ful = false; @@ -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/AudioPort.cpp b/src/core/audio/AudioPort.cpp index e9beb3c0e..71544dde2 100644 --- a/src/core/audio/AudioPort.cpp +++ b/src/core/audio/AudioPort.cpp @@ -118,7 +118,9 @@ void AudioPort::doProcessing() { if( ph->buffer() ) { - if( ph->usesBuffer() ) + if( ph->usesBuffer() + && ( ph->type() == PlayHandle::TypeNotePlayHandle + || !MixHelpers::isSilent( ph->buffer(), fpp ) ) ) { m_bufferUsage = true; MixHelpers::add( m_portBuffer, ph->buffer(), fpp ); @@ -238,7 +240,7 @@ void AudioPort::addPlayHandle( PlayHandle * handle ) void AudioPort::removePlayHandle( PlayHandle * handle ) { m_playHandleLock.lock(); - PlayHandleList::Iterator it = qFind( m_playHandles.begin(), m_playHandles.end(), handle ); + PlayHandleList::Iterator it = std::find( m_playHandles.begin(), m_playHandles.end(), handle ); if( it != m_playHandles.end() ) { m_playHandles.erase( it ); diff --git a/src/core/audio/AudioPortAudio.cpp b/src/core/audio/AudioPortAudio.cpp index b14c1e79d..ad67277ab 100644 --- a/src/core/audio/AudioPortAudio.cpp +++ b/src/core/audio/AudioPortAudio.cpp @@ -27,6 +27,10 @@ #include "AudioPortAudio.h" #ifndef LMMS_HAVE_PORTAUDIO +void AudioPortAudioSetupUtil::updateBackends() +{ +} + void AudioPortAudioSetupUtil::updateDevices() { } @@ -44,21 +48,19 @@ void AudioPortAudioSetupUtil::updateChannels() #include "Engine.h" #include "ConfigManager.h" #include "gui_templates.h" -#include "templates.h" #include "ComboBox.h" #include "Mixer.h" AudioPortAudio::AudioPortAudio( bool & _success_ful, Mixer * _mixer ) : - AudioDevice( tLimit( + AudioDevice( qBound( + DEFAULT_CHANNELS, ConfigManager::inst()->value( "audioportaudio", "channels" ).toInt(), - DEFAULT_CHANNELS, SURROUND_CHANNELS ), - _mixer ), + SURROUND_CHANNELS ), _mixer ), m_paStream( NULL ), m_wasPAInitError( false ), m_outBuf( new surroundSampleFrame[mixer()->framesPerPeriod()] ), - m_outBufPos( 0 ), - m_stopSemaphore( 1 ) + m_outBufPos( 0 ) { _success_ful = false; @@ -167,8 +169,6 @@ AudioPortAudio::AudioPortAudio( bool & _success_ful, Mixer * _mixer ) : printf( "Input device: '%s' backend: '%s'\n", Pa_GetDeviceInfo( inDevIdx )->name, Pa_GetHostApiInfo( Pa_GetDeviceInfo( inDevIdx )->hostApi )->name ); printf( "Output device: '%s' backend: '%s'\n", Pa_GetDeviceInfo( outDevIdx )->name, Pa_GetHostApiInfo( Pa_GetDeviceInfo( outDevIdx )->hostApi )->name ); - m_stopSemaphore.acquire(); - // TODO: debug Mixer::pushInputFrames() //m_supportsCapture = true; @@ -181,7 +181,6 @@ AudioPortAudio::AudioPortAudio( bool & _success_ful, Mixer * _mixer ) : AudioPortAudio::~AudioPortAudio() { stopProcessing(); - m_stopSemaphore.release(); if( !m_wasPAInitError ) { @@ -212,8 +211,7 @@ void AudioPortAudio::stopProcessing() { if( m_paStream && Pa_IsStreamActive( m_paStream ) ) { - m_stopSemaphore.acquire(); - + m_stopped = true; PaError err = Pa_StopStream( m_paStream ); if( err != paNoError ) @@ -283,7 +281,6 @@ int AudioPortAudio::process_callback( if( !frames ) { m_stopped = true; - m_stopSemaphore.release(); memset( _outputBuffer, 0, _framesPerBuffer * channels() * sizeof(float) ); return paComplete; @@ -334,6 +331,28 @@ int AudioPortAudio::_process_callback( + +void AudioPortAudioSetupUtil::updateBackends() +{ + PaError err = Pa_Initialize(); + if( err != paNoError ) { + printf( "Couldn't initialize PortAudio: %s\n", Pa_GetErrorText( err ) ); + return; + } + + const PaHostApiInfo * hi; + for( int i = 0; i < Pa_GetHostApiCount(); ++i ) + { + hi = Pa_GetHostApiInfo( i ); + m_backendModel.addItem( hi->name ); + } + + Pa_Terminate(); +} + + + + void AudioPortAudioSetupUtil::updateDevices() { PaError err = Pa_Initialize(); @@ -393,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 ); @@ -412,40 +431,9 @@ 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 );*/ - // Setup models - PaError err = Pa_Initialize(); - if( err != paNoError ) { - printf( "Couldn't initialize PortAudio: %s\n", Pa_GetErrorText( err ) ); - return; - } - - // todo: setup backend model - const PaHostApiInfo * hi; - for( int i = 0; i < Pa_GetHostApiCount(); ++i ) - { - hi = Pa_GetHostApiInfo( i ); - m_setupUtil.m_backendModel.addItem( hi->name ); - } - - Pa_Terminate(); - - - const QString& backend = ConfigManager::inst()->value( "audioportaudio", - "backend" ); - const QString& device = ConfigManager::inst()->value( "audioportaudio", - "device" ); - - int i = qMax( 0, m_setupUtil.m_backendModel.findText( backend ) ); - m_setupUtil.m_backendModel.setValue( i ); - - m_setupUtil.updateDevices(); - - i = qMax( 0, m_setupUtil.m_deviceModel.findText( device ) ); - m_setupUtil.m_deviceModel.setValue( i ); - connect( &m_setupUtil.m_backendModel, SIGNAL( dataChanged() ), &m_setupUtil, SLOT( updateDevices() ) ); @@ -484,6 +472,33 @@ void AudioPortAudio::setupWidget::saveSettings() } + + +void AudioPortAudio::setupWidget::show() +{ + if( m_setupUtil.m_backendModel.size() == 0 ) + { + // populate the backend model the first time we are shown + m_setupUtil.updateBackends(); + + const QString& backend = ConfigManager::inst()->value( + "audioportaudio", "backend" ); + const QString& device = ConfigManager::inst()->value( + "audioportaudio", "device" ); + + int i = qMax( 0, m_setupUtil.m_backendModel.findText( backend ) ); + m_setupUtil.m_backendModel.setValue( i ); + + m_setupUtil.updateDevices(); + + i = qMax( 0, m_setupUtil.m_deviceModel.findText( device ) ); + m_setupUtil.m_deviceModel.setValue( i ); + } + + AudioDeviceSetupWidget::show(); +} + + #endif diff --git a/src/core/audio/AudioPulseAudio.cpp b/src/core/audio/AudioPulseAudio.cpp index 23031b10c..af14960a7 100644 --- a/src/core/audio/AudioPulseAudio.cpp +++ b/src/core/audio/AudioPulseAudio.cpp @@ -45,10 +45,10 @@ static void stream_write_callback(pa_stream *s, size_t length, void *userdata) AudioPulseAudio::AudioPulseAudio( bool & _success_ful, Mixer* _mixer ) : - AudioDevice( tLimit( + AudioDevice( qBound( + DEFAULT_CHANNELS, ConfigManager::inst()->value( "audiopa", "channels" ).toInt(), - DEFAULT_CHANNELS, SURROUND_CHANNELS ), - _mixer ), + SURROUND_CHANNELS ), _mixer ), m_s( NULL ), m_quit( false ), m_convertEndian( false ) @@ -103,6 +103,7 @@ void AudioPulseAudio::startProcessing() void AudioPulseAudio::stopProcessing() { + m_quit = true; stopProcessingThread( this ); } @@ -138,7 +139,7 @@ static void stream_state_callback( pa_stream *s, void * userdata ) case PA_STREAM_FAILED: default: - qCritical( "Stream errror: %s\n", + qCritical( "Stream error: %s\n", pa_strerror(pa_context_errno( pa_stream_get_context( s ) ) ) ); } @@ -313,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 ); @@ -325,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 2b810e913..b970ba630 100644 --- a/src/core/audio/AudioSdl.cpp +++ b/src/core/audio/AudioSdl.cpp @@ -34,19 +34,21 @@ #include "gui_templates.h" #include "Mixer.h" - AudioSdl::AudioSdl( bool & _success_ful, Mixer* _mixer ) : AudioDevice( DEFAULT_CHANNELS, _mixer ), - m_outBuf( new surroundSampleFrame[mixer()->framesPerPeriod()] ), - m_convertedBufPos( 0 ), - m_convertEndian( false ) + m_outBuf( new surroundSampleFrame[mixer()->framesPerPeriod()] ) { _success_ful = false; +#ifdef LMMS_HAVE_SDL2 + m_currentBufferFramesCount = 0; + m_currentBufferFramePos = 0; +#else m_convertedBufSize = mixer()->framesPerPeriod() * channels() * sizeof( int_sample_t ); + m_convertedBufPos = 0; m_convertedBuf = new Uint8[m_convertedBufSize]; - +#endif if( SDL_Init( SDL_INIT_AUDIO | SDL_INIT_NOPARACHUTE ) < 0 ) { @@ -55,9 +57,15 @@ AudioSdl::AudioSdl( bool & _success_ful, Mixer* _mixer ) : } m_audioHandle.freq = sampleRate(); +#ifdef LMMS_HAVE_SDL2 + m_audioHandle.format = AUDIO_F32SYS; // we want it in byte-order + // of system, so we don't have + // to convert the buffers +#else m_audioHandle.format = AUDIO_S16SYS; // we want it in byte-order // of system, so we don't have // to convert the buffers +#endif m_audioHandle.channels = channels(); m_audioHandle.samples = qMax( 1024, mixer()->framesPerPeriod()*2 ); @@ -66,15 +74,47 @@ AudioSdl::AudioSdl( bool & _success_ful, Mixer* _mixer ) : SDL_AudioSpec actual; +#ifdef LMMS_HAVE_SDL2 + m_outputDevice = SDL_OpenAudioDevice (NULL, + 0, + &m_audioHandle, + &actual, + 0); + if (m_outputDevice == 0) { + qCritical( "Couldn't open SDL-audio: %s\n", SDL_GetError() ); + return; + } +#else // open the audio device, forcing the desired format if( SDL_OpenAudio( &m_audioHandle, &actual ) < 0 ) { qCritical( "Couldn't open SDL-audio: %s\n", SDL_GetError() ); return; } - m_convertEndian = ( m_audioHandle.format != actual.format ); + + m_outConvertEndian = ( m_audioHandle.format != actual.format ); +#endif + _success_ful = true; + +#ifdef LMMS_HAVE_SDL2 + m_inputAudioHandle = m_audioHandle; + m_inputAudioHandle.callback = sdlInputAudioCallback; + + m_inputDevice = SDL_OpenAudioDevice (NULL, + 1, + &m_inputAudioHandle, + &actual, + 0); + if (m_inputDevice != 0) { + m_supportsCapture = true; + } else { + m_supportsCapture = false; + qWarning ( "Couldn't open SDL capture device: %s\n", SDL_GetError ()); + } + +#endif } @@ -84,9 +124,18 @@ AudioSdl::~AudioSdl() { stopProcessing(); +#ifdef LMMS_HAVE_SDL2 + if (m_inputDevice != 0) + SDL_CloseAudioDevice(m_inputDevice); + if (m_outputDevice != 0) + SDL_CloseAudioDevice(m_outputDevice); +#else SDL_CloseAudio(); - SDL_Quit(); delete[] m_convertedBuf; +#endif + + SDL_Quit(); + delete[] m_outBuf; } @@ -97,7 +146,12 @@ void AudioSdl::startProcessing() { m_stopped = false; +#ifdef LMMS_HAVE_SDL2 + SDL_PauseAudioDevice (m_outputDevice, 0); + SDL_PauseAudioDevice (m_inputDevice, 0); +#else SDL_PauseAudio( 0 ); +#endif } @@ -105,12 +159,30 @@ void AudioSdl::startProcessing() void AudioSdl::stopProcessing() { +#ifdef LMMS_HAVE_SDL2 + if( SDL_GetAudioDeviceStatus(m_outputDevice) == SDL_AUDIO_PLAYING ) +#else if( SDL_GetAudioStatus() == SDL_AUDIO_PLAYING ) +#endif { +#ifdef LMMS_HAVE_SDL2 + SDL_LockAudioDevice (m_inputDevice); + SDL_LockAudioDevice (m_outputDevice); + + m_stopped = true; + + SDL_PauseAudioDevice (m_inputDevice, 1); + SDL_PauseAudioDevice (m_outputDevice, 1); + + SDL_UnlockAudioDevice (m_inputDevice); + SDL_UnlockAudioDevice (m_outputDevice); +#else SDL_LockAudio(); m_stopped = true; SDL_PauseAudio( 1 ); SDL_UnlockAudio(); +#endif + } } @@ -119,6 +191,8 @@ void AudioSdl::stopProcessing() void AudioSdl::applyQualitySettings() { + // Better than if (0) +#if 0 if( 0 )//hqAudio() ) { SDL_CloseAudio(); @@ -135,6 +209,7 @@ void AudioSdl::applyQualitySettings() qCritical( "Couldn't open SDL-audio: %s\n", SDL_GetError() ); } } +#endif AudioDevice::applyQualitySettings(); } @@ -160,6 +235,41 @@ void AudioSdl::sdlAudioCallback( Uint8 * _buf, int _len ) return; } + // SDL2: process float samples +#ifdef LMMS_HAVE_SDL2 + while( _len ) + { + if( m_currentBufferFramePos == 0 ) + { + // frames depend on the sample rate + const fpp_t frames = getNextBuffer( m_outBuf ); + if( !frames ) + { + memset( _buf, 0, _len ); + return; + } + m_currentBufferFramesCount = frames; + + } + const uint min_frames_count = qMin( _len/sizeof(sampleFrame), + m_currentBufferFramesCount + - m_currentBufferFramePos ); + + const float gain = mixer()->masterGain(); + for (uint f = 0; f < min_frames_count; f++) + { + (m_outBuf + m_currentBufferFramePos)[f][0] *= gain; + (m_outBuf + m_currentBufferFramePos)[f][1] *= gain; + } + + memcpy( _buf, m_outBuf + m_currentBufferFramePos, min_frames_count*sizeof(sampleFrame) ); + _buf += min_frames_count*sizeof(sampleFrame); + _len -= min_frames_count*sizeof(sampleFrame); + m_currentBufferFramePos += min_frames_count; + + m_currentBufferFramePos %= m_currentBufferFramesCount; + } +#else while( _len ) { if( m_convertedBufPos == 0 ) @@ -168,6 +278,7 @@ void AudioSdl::sdlAudioCallback( Uint8 * _buf, int _len ) const fpp_t frames = getNextBuffer( m_outBuf ); if( !frames ) { + m_stopped = true; memset( _buf, 0, _len ); return; } @@ -177,7 +288,7 @@ void AudioSdl::sdlAudioCallback( Uint8 * _buf, int _len ) convertToS16( m_outBuf, frames, mixer()->masterGain(), (int_sample_t *)m_convertedBuf, - m_convertEndian ); + m_outConvertEndian ); } const int min_len = qMin( _len, m_convertedBufSize - m_convertedBufPos ); @@ -187,10 +298,25 @@ void AudioSdl::sdlAudioCallback( Uint8 * _buf, int _len ) m_convertedBufPos += min_len; m_convertedBufPos %= m_convertedBufSize; } +#endif } +#ifdef LMMS_HAVE_SDL2 +void AudioSdl::sdlInputAudioCallback(void *_udata, Uint8 *_buf, int _len) { + AudioSdl * _this = static_cast( _udata ); + _this->sdlInputAudioCallback( _buf, _len ); +} + +void AudioSdl::sdlInputAudioCallback(Uint8 *_buf, int _len) { + sampleFrame *samples_buffer = (sampleFrame *) _buf; + fpp_t frames = _len / sizeof ( sampleFrame ); + + mixer()->pushInputFrames (samples_buffer, frames); +} + +#endif AudioSdl::setupWidget::setupWidget( QWidget * _parent ) : AudioDeviceSetupWidget( AudioSdl::name(), _parent ) @@ -199,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 3145eb218..24bef9246 100644 --- a/src/core/audio/AudioSndio.cpp +++ b/src/core/audio/AudioSndio.cpp @@ -36,7 +36,6 @@ #include "Mixer.h" #include "Engine.h" #include "gui_templates.h" -#include "templates.h" #ifdef LMMS_HAVE_UNISTD_H #include @@ -50,10 +49,11 @@ AudioSndio::AudioSndio(bool & _success_ful, Mixer * _mixer) : - AudioDevice( tLimit( - ConfigManager::inst()->value( "audiosndio", "channels" ).toInt(), - DEFAULT_CHANNELS, SURROUND_CHANNELS ), _mixer ), - m_convertEndian ( false ) + AudioDevice( qBound( + DEFAULT_CHANNELS, + ConfigManager::inst()->value( "audiosndio", "channels" ).toInt(), + SURROUND_CHANNELS ), _mixer ), + m_convertEndian ( false ) { _success_ful = false; @@ -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 46a0315e7..2c3d493a6 100644 --- a/src/core/audio/AudioSoundIo.cpp +++ b/src/core/audio/AudioSoundIo.cpp @@ -33,14 +33,14 @@ #include "debug.h" #include "ConfigManager.h" #include "gui_templates.h" -#include "templates.h" #include "ComboBox.h" #include "Mixer.h" AudioSoundIo::AudioSoundIo( bool & outSuccessful, Mixer * _mixer ) : - AudioDevice( tLimit( - ConfigManager::inst()->value( "audiosoundio", "channels" ).toInt(), DEFAULT_CHANNELS, SURROUND_CHANNELS ), - _mixer ) + AudioDevice( qBound( + DEFAULT_CHANNELS, + ConfigManager::inst()->value( "audiosoundio", "channels" ).toInt(), + SURROUND_CHANNELS ), _mixer ) { outSuccessful = false; m_soundio = NULL; @@ -49,6 +49,7 @@ AudioSoundIo::AudioSoundIo( bool & outSuccessful, Mixer * _mixer ) : m_disconnectErr = 0; m_outBufFrameIndex = 0; m_outBufFramesTotal = 0; + m_stopped = true; m_soundio = soundio_create(); if (!m_soundio) @@ -210,15 +211,18 @@ void AudioSoundIo::startProcessing() m_outBuf = new surroundSampleFrame[m_outBufSize]; + m_stopped = false; int err; if ((err = soundio_outstream_start(m_outstream))) { + m_stopped = true; fprintf(stderr, "soundio unable to start stream: %s\n", soundio_strerror(err)); } } void AudioSoundIo::stopProcessing() { + m_stopped = true; if (m_outstream) { soundio_outstream_destroy(m_outstream); @@ -244,6 +248,7 @@ void AudioSoundIo::underflowCallback() void AudioSoundIo::writeCallback(int frameCountMin, int frameCountMax) { + if (m_stopped) {return;} const struct SoundIoChannelLayout *layout = &m_outstream->layout; SoundIoChannelArea *areas; int bytesPerSample = m_outstream->bytes_per_sample; @@ -265,11 +270,27 @@ void AudioSoundIo::writeCallback(int frameCountMin, int frameCountMax) if (!frameCount) break; + + if (m_stopped) + { + for (int channel = 0; channel < layout->channel_count; ++channel) + { + memset(areas[channel].ptr, 0, bytesPerSample * frameCount); + areas[channel].ptr += areas[channel].step * frameCount; + } + continue; + } + for (int frame = 0; frame < frameCount; frame += 1) { if (m_outBufFrameIndex >= m_outBufFramesTotal) { m_outBufFramesTotal = getNextBuffer(m_outBuf); + if (m_outBufFramesTotal == 0) + { + m_stopped = true; + break; + } m_outBufFrameIndex = 0; } @@ -405,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/core/fft_helpers.cpp b/src/core/fft_helpers.cpp index a17ebf719..bc7d289e3 100644 --- a/src/core/fft_helpers.cpp +++ b/src/core/fft_helpers.cpp @@ -2,6 +2,7 @@ * fft_helpers.cpp - some functions around FFT analysis * * Copyright (c) 2008-2012 Tobias Doerffel + * Copyright (c) 2019 Martin Pavelek * * This file is part of LMMS - https://lmms.io * @@ -28,127 +29,194 @@ #include #include "lmms_constants.h" -/* returns biggest value from abs_spectrum[spec_size] array - - returns -1 on error -*/ -float maximum(float *abs_spectrum, unsigned int spec_size) +/* Returns biggest value from abs_spectrum[spec_size] array. + * + * return -1 on error, otherwise the maximum value + */ +float maximum(const float *abs_spectrum, unsigned int spec_size) { - float maxi=0; + float maxi = 0; unsigned int i; - if ( abs_spectrum==NULL ) - return -1; + if (abs_spectrum == NULL) {return -1;} + if (spec_size <= 0) {return -1;} - if (spec_size<=0) - return -1; - - for ( i=0; imaxi ) - maxi=abs_spectrum[i]; + if (abs_spectrum[i] > maxi) {maxi = abs_spectrum[i];} } - return maxi; } +float maximum(const std::vector &abs_spectrum) +{ + return maximum(abs_spectrum.data(), abs_spectrum.size()); +} -/* apply hanning or hamming window to channel - returns -1 on error */ -int hanming(float *timebuffer, int length, WINDOWS type) +/* Normalize the array of absolute magnitudes to a 0..1 range. + * Block size refers to FFT block size before any zero padding. + * + * return -1 on error, 0 on success + */ +int normalize(const float *abs_spectrum, float *norm_spectrum, unsigned int bin_count, unsigned int block_size) { int i; - float alpha; - if ( (timebuffer==NULL)||(length<=0) ) - return -1; + if (abs_spectrum == NULL || norm_spectrum == NULL) {return -1;} + if (bin_count == 0 || block_size == 0) {return -1;} + for (i = 0; i < bin_count; i++) + { + norm_spectrum[i] = abs_spectrum[i] / block_size; + } + return 0; +} + +int normalize(const std::vector &abs_spectrum, std::vector &norm_spectrum, unsigned int block_size) +{ + if (abs_spectrum.size() != norm_spectrum.size()) {return -1;} + + return normalize(abs_spectrum.data(), norm_spectrum.data(), abs_spectrum.size(), block_size); +} + + +/* Check if the spectrum contains any non-zero value. + * + * return 1 if spectrum contains any non-zero value + * return 0 otherwise + */ +int notEmpty(const std::vector &spectrum) +{ + for (int i = 0; i < spectrum.size(); i++) + { + if (spectrum[i] != 0) {return 1;} + } + return 0; +} + + +/* Precompute an FFT window function for later real-time use. + * + * return -1 on error + */ +int precomputeWindow(float *window, unsigned int length, FFT_WINDOWS type, bool normalized) +{ + unsigned int i; + float gain = 0; + float a0; + float a1; + float a2; + float a3; + + if (window == NULL) {return -1;} + + // constants taken from + // https://en.wikipedia.org/wiki/Window_function#AList_of_window_functions switch (type) { - case HAMMING: alpha=0.54; break; + default: + case RECTANGULAR: + for (i = 0; i < length; i++) {window[i] = 1.0;} + gain = 1; + return 0; + case BLACKMAN_HARRIS: + a0 = 0.35875; + a1 = 0.48829; + a2 = 0.14128; + a3 = 0.01168; + break; + case HAMMING: + a0 = 0.54; + a1 = 1.0 - a0; + a2 = 0; + a3 = 0; + break; case HANNING: - default: alpha=0.5; break; + a0 = 0.5; + a1 = 1.0 - a0; + a2 = 0; + a3 = 0; + break; } - for ( i=0; i num_new - - returns 0 on success, else -1 */ -int compressbands(float *absspec_buffer, float *compressedband, int num_old, int num_new, int bottom, int top) +/* Build fewer subbands from many absolute spectrum values. + * Take care that - compressedbands[] array num_new elements long + * - num_old > num_new + * + * return 0 on success, else -1 + */ +int compressbands(const float *absspec_buffer, float *compressedband, int num_old, int num_new, int bottom, int top) { float ratio; int i, usefromold; float j; float j_min, j_max; - if ( (absspec_buffer==NULL)||(compressedband==NULL) ) - return -1; + if (absspec_buffer == NULL || compressedband == NULL) {return -1;} + if (num_old < num_new) {return -1;} + if (num_old <= 0 || num_new <= 0) {return -1;} + if (bottom < 0) {bottom = 0;} + if (top >= num_old) {top = num_old - 1;} - if ( num_old=num_old ) - top=num_old-1; - - usefromold=num_old-(num_old-top)-bottom; - - ratio=(float)usefromold/(float)num_new; + ratio = (float)usefromold / (float)num_new; // for each new subband - for ( i=0; i ]\n" - " [ -c ]\n" - " [ -d ]\n" - " [ -f ]\n" - " [ --geometry ]\n" - " [ -h ]\n" - " [ -i ]\n" - " [ --import [-e]]\n" - " [ -l ]\n" - " [ -m ]\n" - " [ -o ]\n" - " [ -p ]\n" - " [ -r ] [ options ]\n" - " [ -s ]\n" - " [ -u ]\n" - " [ -v ]\n" - " [ -x ]\n" - " [ ]\n\n" - "-a, --float 32bit float bit depth\n" - "-b, --bitrate Specify output bitrate in KBit/s\n" - " Default: 160.\n" - "-c, --config Get the configuration from \n" - "-d, --dump Dump XML of compressed file \n" - "-f, --format Specify format of render-output where\n" - " Format is either 'wav', 'flac', 'ogg' or 'mp3'.\n" - " --geometry Specify the size and position of the main window\n" - " geometry is .\n" - "-h, --help Show this usage information and exit.\n" - "-i, --interpolation Specify interpolation method\n" - " Possible values:\n" - " - linear\n" - " - sincfastest (default)\n" - " - sincmedium\n" - " - sincbest\n" - " --import [-e] Import MIDI file .\n" - " If -e is specified lmms exits after importing the file.\n" - "-l, --loop Render as a loop\n" - "-m, --mode Stereo mode used for MP3 export\n" - " Possible values: s, j, m\n" - " s: Stereo\n" - " j: Joint Stereo\n" - " m: Mono\n" - " Default: j\n" - "-o, --output Render into \n" - " For --render, provide a file path\n" - " For --rendertracks, provide a directory path\n" - "-p, --profile Dump profiling information to file \n" - "-r, --render Render given project file\n" - " --rendertracks Render each track to a different file\n" - "-s, --samplerate Specify output samplerate in Hz\n" - " Range: 44100 (default) to 192000\n" - "-u, --upgrade [out] Upgrade file and save as \n" - " Standard out is used if no output file is specifed\n" - "-v, --version Show version information and exit.\n" - " --allowroot Bypass root user startup check (use with caution).\n" - "-x, --oversampling Specify oversampling\n" - " Possible values: 1, 2, 4, 8\n" - " Default: 2\n\n", + "Usage: lmms [global options...] [ [action parameters...]]\n\n" + "Actions:\n" + " [options...] [] Start LMMS in normal GUI mode\n" + " dump Dump XML of compressed file \n" + " render [options...] Render given project file\n" + " rendertracks [options...] Render each track to a different file\n" + " upgrade [out] Upgrade file and save as \n" + " Standard out is used if no output file\n" + " is specified\n" + "\nGlobal options:\n" + " --allowroot Bypass root user startup check (use with\n" + " caution).\n" + " -c, --config Get the configuration from \n" + " -h, --help Show this usage information and exit.\n" + " -v, --version Show version information and exit.\n" + "\nOptions if no action is given:\n" + " --geometry Specify the size and position of\n" + " the main window\n" + " geometry is .\n" + " --import [-e] Import MIDI or Hydrogen file .\n" + " If -e is specified lmms exits after importing the file.\n" + "\nOptions for \"render\" and \"rendertracks\":\n" + " -a, --float Use 32bit float bit depth\n" + " -b, --bitrate Specify output bitrate in KBit/s\n" + " Default: 160.\n" + " -f, --format Specify format of render-output where\n" + " Format is either 'wav', 'flac', 'ogg' or 'mp3'.\n" + " -i, --interpolation Specify interpolation method\n" + " Possible values:\n" + " - linear\n" + " - sincfastest (default)\n" + " - sincmedium\n" + " - sincbest\n" + " -l, --loop Render as a loop\n" + " -m, --mode Stereo mode used for MP3 export\n" + " Possible values: s, j, m\n" + " s: Stereo\n" + " j: Joint Stereo\n" + " m: Mono\n" + " Default: j\n" + " -o, --output Render into \n" + " For \"render\", provide a file path\n" + " For \"rendertracks\", provide a directory path\n" + " If not specified, render will overwrite the input file\n" + " For \"rendertracks\", this might be required\n" + " -p, --profile Dump profiling information to file \n" + " -s, --samplerate Specify output samplerate in Hz\n" + " Range: 44100 (default) to 192000\n" + " -x, --oversampling Specify oversampling\n" + " Possible values: 1, 2, 4, 8\n" + " Default: 2\n\n", LMMS_VERSION, LMMS_PROJECT_COPYRIGHT ); } @@ -251,6 +259,33 @@ int main( int argc, char * * argv ) signal(SIGFPE, signalHandler); #endif +#ifdef LMMS_BUILD_WIN32 + // Don't touch redirected streams here + // GetStdHandle should be called before AttachConsole + HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE); + HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); + HANDLE hStdErr = GetStdHandle(STD_ERROR_HANDLE); + FILE *fIn, *fOut, *fErr; + // Enable console output if available + if (AttachConsole(ATTACH_PARENT_PROCESS)) + { + if (!hStdIn) + { + freopen_s(&fIn, "CONIN$", "r", stdin); + } + if (!hStdOut) + { + freopen_s(&fOut, "CONOUT$", "w", stdout); + } + if (!hStdErr) + { + freopen_s(&fErr, "CONOUT$", "w", stderr); + } + } + // Make Qt's debug message handlers work + qInstallMessageHandler(consoleMessageHandler); +#endif + // initialize memory managers NotePlayHandleManager::init(); @@ -274,11 +309,11 @@ int main( int argc, char * * argv ) if( arg == "--help" || arg == "-h" || arg == "--version" || arg == "-v" || - arg == "--render" || arg == "-r" ) + arg == "render" || arg == "--render" || arg == "-r" ) { coreOnly = true; } - else if( arg == "--rendertracks" ) + else if( arg == "rendertracks" || arg == "--rendertracks" ) { coreOnly = true; renderTracks = true; @@ -309,7 +344,13 @@ int main( int argc, char * * argv ) return EXIT_FAILURE; } #endif - +#ifdef LMMS_BUILD_LINUX + // don't let OS steal the menu bar. FIXME: only effective on Qt4 + QCoreApplication::setAttribute( Qt::AA_DontUseNativeMenuBar ); +#endif +#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) + QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); +#endif QCoreApplication * app = coreOnly ? new QCoreApplication( argc, argv ) : new MainApplication( argc, argv ); @@ -333,7 +374,7 @@ int main( int argc, char * * argv ) printHelp(); return EXIT_SUCCESS; } - else if( arg == "--upgrade" || arg == "-u" ) + else if( arg == "upgrade" || arg == "--upgrade" || arg == "-u") { ++i; @@ -369,7 +410,7 @@ int main( int argc, char * * argv ) #endif } - else if( arg == "--dump" || arg == "-d" ) + else if( arg == "dump" || arg == "--dump" || arg == "-d" ) { ++i; @@ -386,7 +427,8 @@ int main( int argc, char * * argv ) return EXIT_SUCCESS; } - else if( arg == "--render" || arg == "-r" || arg == "--rendertracks" ) + else if( arg == "render" || arg == "--render" || arg == "-r" || + arg == "rendertracks" || arg == "--rendertracks" ) { ++i; @@ -653,6 +695,10 @@ int main( int argc, char * * argv ) ConfigManager::inst()->loadConfigFile(configFile); + // Hidden settings + MixHelpers::setNaNHandler( ConfigManager::inst()->value( "app", + "nanhandler", "1" ).toInt() ); + // set language QString pos = ConfigManager::inst()->value( "app", "language" ); if( pos.isEmpty() ) @@ -675,7 +721,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; @@ -811,29 +857,19 @@ int main( int argc, char * * argv ) ) ); mb.setIcon( QMessageBox::Warning ); - mb.setWindowIcon( embed::getIconPixmap( "icon" ) ); + mb.setWindowIcon( embed::getIconPixmap( "icon_small" ) ); mb.setWindowFlags( Qt::WindowCloseButtonHint ); QPushButton * recover; QPushButton * discard; QPushButton * exit; - #if QT_VERSION >= 0x050000 - // setting all buttons to the same roles allows us - // to have a custom layout - discard = mb.addButton( MainWindow::tr( "Discard" ), - QMessageBox::AcceptRole ); - recover = mb.addButton( MainWindow::tr( "Recover" ), - QMessageBox::AcceptRole ); - - # else - // in qt4 the button order is reversed - recover = mb.addButton( MainWindow::tr( "Recover" ), - QMessageBox::AcceptRole ); - discard = mb.addButton( MainWindow::tr( "Discard" ), - QMessageBox::AcceptRole ); - - #endif + // setting all buttons to the same roles allows us + // to have a custom layout + discard = mb.addButton( MainWindow::tr( "Discard" ), + QMessageBox::AcceptRole ); + recover = mb.addButton( MainWindow::tr( "Recover" ), + QMessageBox::AcceptRole ); // have a hidden exit button exit = mb.addButton( "", QMessageBox::RejectRole); @@ -947,5 +983,15 @@ int main( int argc, char * * argv ) printf( "\n" ); } +#ifdef LMMS_BUILD_WIN32 + // Cleanup console + HWND hConsole = GetConsoleWindow(); + if (hConsole) + { + SendMessage(hConsole, WM_CHAR, (WPARAM)VK_RETURN, (LPARAM)0); + FreeConsole(); + } +#endif + return ret; } diff --git a/src/core/midi/MidiAlsaSeq.cpp b/src/core/midi/MidiAlsaSeq.cpp index be1e623de..56fd956d4 100644 --- a/src/core/midi/MidiAlsaSeq.cpp +++ b/src/core/midi/MidiAlsaSeq.cpp @@ -100,7 +100,7 @@ MidiAlsaSeq::MidiAlsaSeq() : snd_seq_start_queue( m_seqHandle, m_queueID, NULL ); changeQueueTempo( Engine::getSong()->getTempo() ); connect( Engine::getSong(), SIGNAL( tempoChanged( bpm_t ) ), - this, SLOT( changeQueueTempo( bpm_t ) ) ); + this, SLOT( changeQueueTempo( bpm_t ) ), Qt::DirectConnection ); // initial list-update updatePortList(); @@ -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..e37f59c06 100644 --- a/src/core/midi/MidiClient.cpp +++ b/src/core/midi/MidiClient.cpp @@ -77,7 +77,7 @@ void MidiClient::removePort( MidiPort* port ) } QVector::Iterator it = - qFind( m_midiPorts.begin(), m_midiPorts.end(), port ); + std::find( m_midiPorts.begin(), m_midiPorts.end(), port ); if( it != m_midiPorts.end() ) { m_midiPorts.erase( it ); @@ -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] ); diff --git a/src/core/midi/MidiJack.cpp b/src/core/midi/MidiJack.cpp index cea7f7381..568b6dae1 100644 --- a/src/core/midi/MidiJack.cpp +++ b/src/core/midi/MidiJack.cpp @@ -61,6 +61,7 @@ static void JackMidiShutdown(void *arg) MidiJack::MidiJack() : MidiClientRaw(), + m_jackClient( nullptr ), m_input_port( NULL ), m_output_port( NULL ), m_quit( false ) 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; } diff --git a/src/core/midi/MidiPort.cpp b/src/core/midi/MidiPort.cpp index 9e3cdb13d..52e0a5223 100644 --- a/src/core/midi/MidiPort.cpp +++ b/src/core/midi/MidiPort.cpp @@ -63,9 +63,12 @@ MidiPort::MidiPort( const QString& name, m_readableModel.setValue( m_mode == Input || m_mode == Duplex ); m_writableModel.setValue( m_mode == Output || m_mode == Duplex ); - connect( &m_readableModel, SIGNAL( dataChanged() ), this, SLOT( updateMidiPortMode() ) ); - connect( &m_writableModel, SIGNAL( dataChanged() ), this, SLOT( updateMidiPortMode() ) ); - connect( &m_outputProgramModel, SIGNAL( dataChanged() ), this, SLOT( updateOutputProgram() ) ); + connect( &m_readableModel, SIGNAL( dataChanged() ), + this, SLOT( updateMidiPortMode() ), Qt::DirectConnection ); + connect( &m_writableModel, SIGNAL( dataChanged() ), + this, SLOT( updateMidiPortMode() ), Qt::DirectConnection ); + connect( &m_outputProgramModel, SIGNAL( dataChanged() ), + this, SLOT( updateOutputProgram() ), Qt::DirectConnection ); // when using with non-raw-clients we can provide buttons showing diff --git a/src/core/midi/MidiTime.cpp b/src/core/midi/MidiTime.cpp index b4607aee9..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 ) { } @@ -63,19 +63,24 @@ MidiTime::MidiTime( const tick_t ticks ) : { } -MidiTime MidiTime::toNearestTact() const +MidiTime MidiTime::quantize(float bars) const { - if( m_ticks % s_ticksPerTact >= s_ticksPerTact/2 ) - { - return ( getTact() + 1 ) * s_ticksPerTact; - } - return getTact() * s_ticksPerTact; + //The intervals we should snap to, our new position should be a factor of this + int interval = s_ticksPerBar * bars; + //The lower position we could snap to + int lowPos = m_ticks / interval; + //Offset from the lower position + int offset = m_ticks % interval; + //1 if we should snap up, 0 if we shouldn't + int snapUp = offset / (interval / 2); + + return (lowPos + snapUp) * interval; } -MidiTime MidiTime::toAbsoluteTact() const +MidiTime MidiTime::toAbsoluteBar() const { - return getTact() * s_ticksPerTact; + return getBar() * s_ticksPerBar; } @@ -93,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; } @@ -126,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 ); } @@ -155,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 ) @@ -166,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/core/midi/MidiWinMM.cpp b/src/core/midi/MidiWinMM.cpp index a59ebc69e..ef60f3015 100644 --- a/src/core/midi/MidiWinMM.cpp +++ b/src/core/midi/MidiWinMM.cpp @@ -248,9 +248,13 @@ void MidiWinMM::closeDevices() m_outputSubs.clear(); QMapIterator i( m_inputDevices ); + + HMIDIIN hInDev; while( i.hasNext() ) { - midiInClose( i.next().key() ); + hInDev = i.next().key(); + midiInReset( hInDev ); + midiInClose( hInDev ); } QMapIterator o( m_outputDevices ); 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/AutomatableModelView.cpp b/src/gui/AutomatableModelView.cpp index 0597cf2f5..039c75c99 100644 --- a/src/gui/AutomatableModelView.cpp +++ b/src/gui/AutomatableModelView.cpp @@ -42,9 +42,7 @@ static float floatFromClipboard(bool* ok=nullptr); AutomatableModelView::AutomatableModelView( ::Model* model, QWidget* _this ) : - ModelView( model, _this ), - m_description( QString::null ), - m_unit( QString::null ) + ModelView( model, _this ) { widget()->setAcceptDrops( true ); widget()->setCursor( QCursor( embed::getIconPixmap( "hand" ), 3, 3 ) ); diff --git a/src/gui/AutomationPatternView.cpp b/src/gui/AutomationPatternView.cpp index 92e7b7377..130d51a0e 100644 --- a/src/gui/AutomationPatternView.cpp +++ b/src/gui/AutomationPatternView.cpp @@ -91,7 +91,7 @@ void AutomationPatternView::update() void AutomationPatternView::resetName() { - m_pat->setName( QString::null ); + m_pat->setName( QString() ); } @@ -118,7 +118,7 @@ void AutomationPatternView::disconnectObject( QAction * _a ) float oldMin = m_pat->getMin(); float oldMax = m_pat->getMax(); - m_pat->m_objects.erase( qFind( m_pat->m_objects.begin(), + m_pat->m_objects.erase( std::find( m_pat->m_objects.begin(), m_pat->m_objects.end(), dynamic_cast( j ) ) ); update(); @@ -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 ); @@ -366,15 +366,15 @@ void AutomationPatternView::paintEvent( QPaintEvent * ) } p.setRenderHints( QPainter::Antialiasing, false ); - p.resetMatrix(); + p.resetTransform(); // bar lines 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/CMakeLists.txt b/src/gui/CMakeLists.txt index 040c64bc2..8c489576b 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -43,6 +43,9 @@ SET(LMMS_SRCS gui/editors/PianoRoll.cpp gui/editors/SongEditor.cpp + gui/menus/RecentProjectsMenu.cpp + gui/menus/TemplatesMenu.cpp + gui/widgets/AutomatableButton.cpp gui/widgets/AutomatableSlider.cpp gui/widgets/CaptionMenu.cpp @@ -56,6 +59,7 @@ SET(LMMS_SRCS gui/widgets/FadeButton.cpp gui/widgets/Fader.cpp gui/widgets/FxLine.cpp + gui/widgets/FxLineLcdSpinBox.cpp gui/widgets/Graph.cpp gui/widgets/GrooveView.cpp gui/widgets/GroupBox.cpp @@ -88,6 +92,7 @@ SET(LMMS_SRCS gui/widgets/TrackLabelButton.cpp gui/widgets/TrackRenameLineEdit.cpp gui/widgets/VisualizationWidget.cpp + gui/widgets/StepRecorderWidget.cpp PARENT_SCOPE ) 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/EffectControlDialog.cpp b/src/gui/EffectControlDialog.cpp index c43f451aa..dc273a6a3 100644 --- a/src/gui/EffectControlDialog.cpp +++ b/src/gui/EffectControlDialog.cpp @@ -36,6 +36,7 @@ EffectControlDialog::EffectControlDialog( EffectControls * _controls ) : m_effectControls( _controls ) { setWindowTitle( m_effectControls->effect()->displayName() ); + setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ); } diff --git a/src/gui/EffectSelectDialog.cpp b/src/gui/EffectSelectDialog.cpp index deb39d901..79e40427b 100644 --- a/src/gui/EffectSelectDialog.cpp +++ b/src/gui/EffectSelectDialog.cpp @@ -27,6 +27,7 @@ #include "ui_EffectSelectDialog.h" #include "gui_templates.h" +#include "DummyEffect.h" #include "embed.h" #include "PluginFactory.h" @@ -53,11 +54,6 @@ EffectSelectDialog::EffectSelectDialog( QWidget * _parent ) : if( desc->subPluginFeatures ) { desc->subPluginFeatures->listSubPluginKeys( - // as iterators are always stated to be not - // equal with pointers, we dereference the - // iterator and take the address of the item, - // so we're on the safe side and the compiler - // likely will reduce that to just "it" desc, subPluginEffectKeys ); } @@ -79,14 +75,14 @@ EffectSelectDialog::EffectSelectDialog( QWidget * _parent ) : { QString name; QString type; - if( ( *it ).desc->subPluginFeatures ) + if( it->desc->subPluginFeatures ) { - name = ( *it ).name; - type = ( *it ).desc->displayName; + name = it->displayName(); + type = it->desc->displayName; } else { - name = ( *it ).desc->displayName; + name = it->desc->displayName; type = "LMMS"; } m_sourceModel.setItem( row, 0, new QStandardItem( name ) ); @@ -120,21 +116,15 @@ EffectSelectDialog::EffectSelectDialog( QWidget * _parent ) : connect( ui->buttonBox, SIGNAL( accepted() ), this, SLOT( acceptSelection() ) ); -#if QT_VERSION >= 0x050000 -#define setResizeMode setSectionResizeMode ui->filterEdit->setClearButtonEnabled( true ); -#endif - ui->pluginList->verticalHeader()->setResizeMode( + ui->pluginList->verticalHeader()->setSectionResizeMode( QHeaderView::ResizeToContents ); ui->pluginList->verticalHeader()->hide(); - ui->pluginList->horizontalHeader()->setResizeMode( 0, + ui->pluginList->horizontalHeader()->setSectionResizeMode( 0, QHeaderView::Stretch ); - ui->pluginList->horizontalHeader()->setResizeMode( 1, + ui->pluginList->horizontalHeader()->setSectionResizeMode( 1, QHeaderView::ResizeToContents ); ui->pluginList->sortByColumn( 0, Qt::AscendingOrder ); -#if QT_VERSION >= 0x050000 -#undef setResizeMode -#endif updateSelection(); show(); @@ -153,12 +143,17 @@ EffectSelectDialog::~EffectSelectDialog() Effect * EffectSelectDialog::instantiateSelectedPlugin( EffectChain * _parent ) { - if( !m_currentSelection.name.isEmpty() && m_currentSelection.desc ) + Effect* result = nullptr; + if(!m_currentSelection.name.isEmpty() && m_currentSelection.desc) { - return Effect::instantiate( m_currentSelection.desc->name, - _parent, &m_currentSelection ); + result = Effect::instantiate(m_currentSelection.desc->name, + _parent, &m_currentSelection); } - return NULL; + if(!result) + { + result = new DummyEffect(_parent, QDomElement()); + } + return result; } @@ -190,62 +185,63 @@ void EffectSelectDialog::rowChanged( const QModelIndex & _idx, { m_currentSelection = m_effectKeys[m_model.mapToSource( _idx ).row()]; } - if( m_currentSelection.desc ) + if( m_currentSelection.desc ) { m_descriptionWidget = new QWidget; - QHBoxLayout *hbox = new QHBoxLayout( m_descriptionWidget ); + QHBoxLayout *hbox = new QHBoxLayout( m_descriptionWidget ); - Plugin::Descriptor const & descriptor = *( m_currentSelection.desc ); + Plugin::Descriptor const & descriptor = *( m_currentSelection.desc ); - if ( descriptor.logo ) - { - QLabel *logoLabel = new QLabel( m_descriptionWidget ); - logoLabel->setPixmap( descriptor.logo->pixmap() ); - logoLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); + const PixmapLoader* pixLoa = m_currentSelection.logo(); + if (pixLoa) + { + QLabel *logoLabel = new QLabel( m_descriptionWidget ); + logoLabel->setPixmap(pixLoa->pixmap()); + logoLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); - hbox->addWidget( logoLabel ); - hbox->setAlignment( logoLabel, Qt::AlignTop); - } + hbox->addWidget( logoLabel ); + hbox->setAlignment( logoLabel, Qt::AlignTop); + } - QWidget *textualInfoWidget = new QWidget( m_descriptionWidget ); + QWidget *textualInfoWidget = new QWidget( m_descriptionWidget ); - hbox->addWidget(textualInfoWidget); + hbox->addWidget(textualInfoWidget); - QVBoxLayout * textWidgetLayout = new QVBoxLayout( textualInfoWidget); - textWidgetLayout->setMargin( 4 ); - textWidgetLayout->setSpacing( 0 ); + QVBoxLayout * textWidgetLayout = new QVBoxLayout( textualInfoWidget); + textWidgetLayout->setMargin( 4 ); + textWidgetLayout->setSpacing( 0 ); - if ( m_currentSelection.desc->subPluginFeatures ) - { - QWidget *subWidget = new QWidget(textualInfoWidget); - QVBoxLayout * subLayout = new QVBoxLayout( subWidget ); - subLayout->setMargin( 4 ); - subLayout->setSpacing( 0 ); - m_currentSelection.desc->subPluginFeatures-> - fillDescriptionWidget( subWidget, &m_currentSelection ); - for( QWidget * w : subWidget->findChildren() ) - { - if( w->parent() == subWidget ) - { - subLayout->addWidget( w ); - } - } + if ( m_currentSelection.desc->subPluginFeatures ) + { + QWidget *subWidget = new QWidget(textualInfoWidget); + QVBoxLayout * subLayout = new QVBoxLayout( subWidget ); + subLayout->setMargin( 4 ); + subLayout->setSpacing( 0 ); + m_currentSelection.desc->subPluginFeatures-> + fillDescriptionWidget( subWidget, &m_currentSelection ); + for( QWidget * w : subWidget->findChildren() ) + { + if( w->parent() == subWidget ) + { + subLayout->addWidget( w ); + } + } - textWidgetLayout->addWidget(subWidget); - } - else - { - QLabel *label = new QLabel(m_descriptionWidget); - QString labelText = "

" + tr("Name") + ": " + QString::fromUtf8(descriptor.displayName) + "

"; - labelText += "

" + tr("Description") + ": " + qApp->translate( "pluginBrowser", descriptor.description ) + "

"; - labelText += "

" + tr("Author") + ": " + QString::fromUtf8(descriptor.author) + "

"; + textWidgetLayout->addWidget(subWidget); + } + else + { + QLabel *label = new QLabel(m_descriptionWidget); + QString labelText = "

" + tr("Name") + ": " + QString::fromUtf8(descriptor.displayName) + "

"; + labelText += "

" + tr("Description") + ": " + qApp->translate( "pluginBrowser", descriptor.description ) + "

"; + labelText += "

" + tr("Author") + ": " + QString::fromUtf8(descriptor.author) + "

"; - label->setText(labelText); - textWidgetLayout->addWidget(label); - } + label->setText(labelText); + textWidgetLayout->addWidget(label); + } - ui->scrollArea->setWidget( m_descriptionWidget ); + ui->scrollArea->setWidget( m_descriptionWidget ); m_descriptionWidget->show(); } } diff --git a/src/gui/ExportProjectDialog.cpp b/src/gui/ExportProjectDialog.cpp index b50c9941b..f3b432f99 100644 --- a/src/gui/ExportProjectDialog.cpp +++ b/src/gui/ExportProjectDialog.cpp @@ -128,6 +128,7 @@ void ExportProjectDialog::accept() void ExportProjectDialog::closeEvent( QCloseEvent * _ce ) { + Engine::getSong()->setLoopRenderCount(1); if( m_renderManager ) { m_renderManager->abortProcessing(); } @@ -187,6 +188,7 @@ void ExportProjectDialog::startExport() Engine::getSong()->setExportLoop( exportLoopCB->isChecked() ); Engine::getSong()->setRenderBetweenMarkers( renderMarkersCB->isChecked() ); + Engine::getSong()->setLoopRenderCount(loopCountSB->value()); connect( m_renderManager.get(), SIGNAL( progressChanged( int ) ), progressBar, SLOT( setValue( int ) ) ); diff --git a/src/gui/FileBrowser.cpp b/src/gui/FileBrowser.cpp index 91804d136..7eeb87ed2 100644 --- a/src/gui/FileBrowser.cpp +++ b/src/gui/FileBrowser.cpp @@ -83,15 +83,13 @@ FileBrowser::FileBrowser(const QString & directories, const QString & filter, m_filterEdit = new QLineEdit( searchWidget ); m_filterEdit->setPlaceholderText( tr("Search") ); -#if QT_VERSION >= 0x050000 m_filterEdit->setClearButtonEnabled( true ); -#endif connect( m_filterEdit, SIGNAL( textEdited( const QString & ) ), this, SLOT( filterItems( const QString & ) ) ); QPushButton * reload_btn = new QPushButton( embed::getIconPixmap( "reload" ), - QString::null, searchWidget ); + QString(), searchWidget ); reload_btn->setToolTip( tr( "Refresh list" ) ); connect( reload_btn, SIGNAL( clicked() ), this, SLOT( reloadTree() ) ); @@ -131,7 +129,7 @@ bool FileBrowser::filterItems( const QString & filter, QTreeWidgetItem * item ) { // yes, then show everything below it->setHidden( false ); - filterItems( QString::null, it ); + filterItems( QString(), it ); anyMatched = true; } else @@ -165,6 +163,7 @@ bool FileBrowser::filterItems( const QString & filter, QTreeWidgetItem * item ) void FileBrowser::reloadTree( void ) { + QList expandedDirs = m_fileBrowserTreeWidget->expandedDirs(); const QString text = m_filterEdit->text(); m_filterEdit->clear(); m_fileBrowserTreeWidget->clear(); @@ -173,17 +172,17 @@ void FileBrowser::reloadTree( void ) { addItems( *it ); } - expandItems(); + expandItems(NULL, expandedDirs); m_filterEdit->setText( text ); filterItems( text ); } -void FileBrowser::expandItems( QTreeWidgetItem * item ) +void FileBrowser::expandItems( QTreeWidgetItem * item, QList expandedDirs ) { - int numChildren = item ? item->childCount() : m_fileBrowserTreeWidget->topLevelItemCount(); - for( int i = 0; i < numChildren; ++i ) + int numChildren = item ? item->childCount() : m_fileBrowserTreeWidget->topLevelItemCount(); + for (int i = 0; i < numChildren; ++i) { QTreeWidgetItem * it = item ? item->child( i ) : m_fileBrowserTreeWidget->topLevelItem(i); if ( m_recurse ) @@ -191,14 +190,15 @@ void FileBrowser::expandItems( QTreeWidgetItem * item ) it->setExpanded( true ); } Directory *d = dynamic_cast ( it ); - if( d ) + if (d) { d->update(); - d->setExpanded( false ); + bool expand = expandedDirs.contains( d->fullName() ); + d->setExpanded( expand ); } - if( m_recurse && it->childCount() ) + if (m_recurse && it->childCount()) { - expandItems(it); + expandItems(it, expandedDirs); } } } @@ -221,7 +221,7 @@ void FileBrowser::addItems(const QString & path ) { if( m_dirsAsItems ) { - m_fileBrowserTreeWidget->addTopLevelItem( new Directory( path, QString::null, m_filter ) ); + m_fileBrowserTreeWidget->addTopLevelItem( new Directory( path, QString(), m_filter ) ); return; } @@ -243,7 +243,7 @@ void FileBrowser::addItems(const QString & path ) Directory *dd = new Directory( cur_file, path, m_filter ); m_fileBrowserTreeWidget->insertTopLevelItem( i,dd ); - dd->update(); + dd->update(); // add files to the directory orphan = false; break; } @@ -328,6 +328,30 @@ FileBrowserTreeWidget::FileBrowserTreeWidget(QWidget * parent ) : } +QList FileBrowserTreeWidget::expandedDirs( QTreeWidgetItem * item ) const +{ + int numChildren = item ? item->childCount() : topLevelItemCount(); + QList dirs; + for (int i = 0; i < numChildren; ++i) + { + QTreeWidgetItem * it = item ? item->child(i) : topLevelItem(i); + + // Add expanded top level directories. + if (it->isExpanded() && (it->type() == TypeDirectoryItem)) + { + Directory *d = static_cast ( it ); + dirs.append( d->fullName() ); + } + + // Add expanded child directories (recurse). + if (it->childCount()) + { + dirs.append( expandedDirs( it ) ); + } + } + return dirs; +} + void FileBrowserTreeWidget::contextMenuEvent(QContextMenuEvent * e ) { FileItem * f = dynamic_cast( itemAt( e->pos() ) ); @@ -408,7 +432,7 @@ void FileBrowserTreeWidget::mousePressEvent(QMouseEvent * me ) delete tf; } else if( ( f->extension ()== "xiz" || f->extension() == "sf2" || f->extension() == "sf3" || f->extension() == "gig" || f->extension() == "pat" ) && - ! pluginFactory->pluginSupportingExtension(f->extension()).isNull() ) + ! pluginFactory->pluginSupportingExtension(f->extension()).info.isNull() ) { m_previewPlayHandle = new PresetPreviewPlayHandle( f->fullName(), f->handling() == FileItem::LoadByPlugin ); } @@ -551,8 +575,9 @@ void FileBrowserTreeWidget::handleFile(FileItem * f, InstrumentTrack * it ) if( i == NULL || !i->descriptor()->supportsFileType( e ) ) { - i = it->loadInstrument( - pluginFactory->pluginSupportingExtension(e).name() ); + PluginFactory::PluginInfoAndKey piakn = + pluginFactory->pluginSupportingExtension(e); + i = it->loadInstrument(piakn.info.name(), &piakn.key); } i->loadFile( f->fullName() ); break; diff --git a/src/gui/FxMixerView.cpp b/src/gui/FxMixerView.cpp index cbcfd0a47..54bbff70f 100644 --- a/src/gui/FxMixerView.cpp +++ b/src/gui/FxMixerView.cpp @@ -47,6 +47,7 @@ #include "Mixer.h" #include "gui_templates.h" #include "InstrumentTrack.h" +#include "SampleTrack.h" #include "Song.h" #include "BBTrackContainer.h" @@ -73,7 +74,7 @@ FxMixerView::FxMixerView() : // Set margins ml->setContentsMargins( 0, 4, 0, 0 ); - + // Channel area m_channelAreaWidget = new QWidget; chLayout = new QHBoxLayout( m_channelAreaWidget ); @@ -114,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 ); } @@ -131,16 +132,16 @@ FxMixerView::FxMixerView() : ml->addWidget( channelArea, 1, Qt::AlignTop ); // show the add new effect channel button - QPushButton * newChannelBtn = new QPushButton( embed::getIconPixmap( "new_channel" ), QString::null, this ); + QPushButton * newChannelBtn = new QPushButton( embed::getIconPixmap( "new_channel" ), QString(), this ); newChannelBtn->setObjectName( "newChannelBtn" ); newChannelBtn->setFixedSize( fxLineSize ); connect( newChannelBtn, SIGNAL( clicked() ), this, SLOT( addNewChannel() ) ); ml->addWidget( newChannelBtn, 0, Qt::AlignTop ); - // add the stacked layout for the effect racks of fx channels + // add the stacked layout for the effect racks of fx channels ml->addWidget( m_racksWidget, 0, Qt::AlignTop | Qt::AlignRight ); - + setCurrentFxLine( m_fxChannelViews[0]->m_fxLine ); setLayout( ml ); @@ -219,10 +220,10 @@ void FxMixerView::refreshDisplay() chLayout->addWidget(m_fxChannelViews[i]->m_fxLine); m_racksLayout->addWidget( m_fxChannelViews[i]->m_rackView ); } - + // set selected fx line to 0 setCurrentFxLine( 0 ); - + // update all fx lines for( int i = 0; i < m_fxChannelViews.size(); ++i ) { @@ -251,6 +252,12 @@ void FxMixerView::updateMaxChannelSelector() inst->effectChannelModel()->setRange(0, m_fxChannelViews.size()-1,1); } + else if( trackList[i]->type() == Track::SampleTrack ) + { + SampleTrack * strk = (SampleTrack *) trackList[i]; + strk->effectChannelModel()->setRange(0, + m_fxChannelViews.size()-1,1); + } } } } @@ -306,9 +313,9 @@ FxMixerView::FxChannelView::FxChannelView(QWidget * _parent, FxMixerView * _mv, m_soloBtn->setCheckable( true ); m_soloBtn->move( 9, m_fader->y()-21); connect(&fxChannel->m_soloModel, SIGNAL( dataChanged() ), - _mv, SLOT ( toggledSolo() ) ); + _mv, SLOT ( toggledSolo() ), Qt::DirectConnection ); ToolTip::add( m_soloBtn, tr( "Solo FX channel" ) ); - + // Create EffectRack for the channel m_rackView = new EffectRackView( &fxChannel->m_fxChain, _mv->m_racksWidget ); m_rackView->setFixedSize( 245, FxLine::FxLineHeight ); @@ -354,6 +361,8 @@ void FxMixerView::updateFxLine(int index) // does current channel send to this channel? int selIndex = m_currentFxLine->channelIndex(); FxLine * thisLine = m_fxChannelViews[index]->m_fxLine; + thisLine->setToolTip( Engine::fxMixer()->effectChannel( index )->m_name ); + FloatModel * sendModel = mix->channelSendModel(selIndex, index); if( sendModel == NULL ) { @@ -590,25 +599,27 @@ void FxMixerView::updateFaders() { const float opl = m_fxChannelViews[i]->m_fader->getPeak_L(); const float opr = m_fxChannelViews[i]->m_fader->getPeak_R(); - const float fall_off = 1.2; - if( m->effectChannel(i)->m_peakLeft > opl ) + const float fallOff = 1.25; + if( m->effectChannel(i)->m_peakLeft >= opl/fallOff ) { m_fxChannelViews[i]->m_fader->setPeak_L( m->effectChannel(i)->m_peakLeft ); - m->effectChannel(i)->m_peakLeft = 0; + // Set to -1 so later we'll know if this value has been refreshed yet. + m->effectChannel(i)->m_peakLeft = -1; } - else + else if( m->effectChannel(i)->m_peakLeft != -1 ) { - m_fxChannelViews[i]->m_fader->setPeak_L( opl/fall_off ); + m_fxChannelViews[i]->m_fader->setPeak_L( opl/fallOff ); } - if( m->effectChannel(i)->m_peakRight > opr ) + if( m->effectChannel(i)->m_peakRight >= opr/fallOff ) { m_fxChannelViews[i]->m_fader->setPeak_R( m->effectChannel(i)->m_peakRight ); - m->effectChannel(i)->m_peakRight = 0; + // Set to -1 so later we'll know if this value has been refreshed yet. + m->effectChannel(i)->m_peakRight = -1; } - else + else if( m->effectChannel(i)->m_peakRight != -1 ) { - m_fxChannelViews[i]->m_fader->setPeak_R( opr/fall_off ); + m_fxChannelViews[i]->m_fader->setPeak_R( opr/fallOff ); } } } diff --git a/src/gui/GuiApplication.cpp b/src/gui/GuiApplication.cpp index 2b3ac48de..a107a7604 100644 --- a/src/gui/GuiApplication.cpp +++ b/src/gui/GuiApplication.cpp @@ -56,11 +56,6 @@ GuiApplication* GuiApplication::instance() GuiApplication::GuiApplication() { - // enable HiDPI scaling before showing anything (Qt 5.6+ only) - #if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)) - QApplication::setAttribute(Qt::AA_EnableHighDpiScaling, true); - #endif - // prompt the user to create the LMMS working directory (e.g. ~/Documents/lmms) if it doesn't exist if ( !ConfigManager::inst()->hasWorkingDir() && QMessageBox::question( NULL, @@ -73,8 +68,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/InstrumentView.cpp b/src/gui/InstrumentView.cpp index 9e8fc58c1..f6d214926 100644 --- a/src/gui/InstrumentView.cpp +++ b/src/gui/InstrumentView.cpp @@ -34,7 +34,6 @@ InstrumentView::InstrumentView( Instrument * _Instrument, QWidget * _parent ) : PluginView( _Instrument, _parent ) { setModel( _Instrument ); - setFixedSize( 250, 250 ); setAttribute( Qt::WA_DeleteOnClose, true ); } @@ -57,7 +56,7 @@ void InstrumentView::setModel( Model * _model, bool ) if( dynamic_cast( _model ) != NULL ) { ModelView::setModel( _model ); - instrumentTrackWindow()->setWindowIcon( model()->descriptor()->logo->pixmap() ); + instrumentTrackWindow()->setWindowIcon( model()->logo()->pixmap() ); connect( model(), SIGNAL( destroyed( QObject * ) ), this, SLOT( close() ) ); } } @@ -71,3 +70,10 @@ InstrumentTrackWindow * InstrumentView::instrumentTrackWindow( void ) parentWidget()->parentWidget() ) ); } + + + +InstrumentViewFixedSize::~InstrumentViewFixedSize() +{ +} + 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; } diff --git a/src/gui/LmmsStyle.cpp b/src/gui/LmmsStyle.cpp index e57e29e47..b6a139bbb 100644 --- a/src/gui/LmmsStyle.cpp +++ b/src/gui/LmmsStyle.cpp @@ -132,11 +132,7 @@ LmmsStyle::LmmsStyle() : if( s_palette != NULL ) { qApp->setPalette( *s_palette ); } -#if QT_VERSION >= 0x050000 setBaseStyle( QStyleFactory::create( "Fusion" ) ); -#else - setBaseStyle( QStyleFactory::create( "Plastique" ) ); -#endif } diff --git a/src/gui/MainApplication.cpp b/src/gui/MainApplication.cpp index 5210dd76c..8eee9b5d0 100644 --- a/src/gui/MainApplication.cpp +++ b/src/gui/MainApplication.cpp @@ -3,7 +3,7 @@ * * Copyright (c) 2017-2017 Tres Finocchiaro * - * This file is part of LMMS - http://lmms.io + * 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 @@ -35,7 +35,7 @@ MainApplication::MainApplication(int& argc, char** argv) : QApplication(argc, argv), m_queuedFile() { -#if defined(LMMS_BUILD_WIN32) && QT_VERSION >= 0x050000 +#if defined(LMMS_BUILD_WIN32) installNativeEventFilter(this); #endif } @@ -92,7 +92,6 @@ bool MainApplication::winEventFilter(MSG* msg, long* result) } } -#if QT_VERSION >= 0x050000 bool MainApplication::nativeEventFilter(const QByteArray& eventType, void* message, long* result) { @@ -103,4 +102,3 @@ bool MainApplication::nativeEventFilter(const QByteArray& eventType, return false; } #endif -#endif diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index ae24e4825..f34128ad4 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -57,10 +57,12 @@ #include "ProjectJournal.h" #include "ProjectNotes.h" #include "ProjectRenderer.h" +#include "RecentProjectsMenu.h" #include "RemotePlugin.h" #include "SetupDialog.h" #include "SideBar.h" #include "SongEditor.h" +#include "TemplatesMenu.h" #include "TextFloat.h" #include "TimeLineWidget.h" #include "ToolButton.h" @@ -69,13 +71,13 @@ #include "lmmsversion.h" -#if !defined(LMMS_BUILD_WIN32) && !defined(LMMS_BUILD_APPLE) && !defined(LMMS_BUILD_HAIKU) && QT_VERSION >= 0x050000 +#if !defined(LMMS_BUILD_WIN32) && !defined(LMMS_BUILD_APPLE) && !defined(LMMS_BUILD_HAIKU) //Work around an issue on KDE5 as per https://bugs.kde.org/show_bug.cgi?id=337491#c21 void disableAutoKeyAccelerators(QWidget* mainWindow) { using DisablerFunc = void(*)(QWidget*); QLibrary kf5WidgetsAddon("KF5WidgetsAddons", 5); - DisablerFunc setNoAccelerators = + DisablerFunc setNoAccelerators = reinterpret_cast(kf5WidgetsAddon.resolve("_ZN19KAcceleratorManager10setNoAccelEP7QWidget")); if(setNoAccelerators) { @@ -88,15 +90,13 @@ void disableAutoKeyAccelerators(QWidget* mainWindow) MainWindow::MainWindow() : m_workspace( NULL ), - m_templatesMenu( NULL ), - m_recentlyOpenedProjectsMenu( NULL ), m_toolsMenu( NULL ), m_autoSaveTimer( this ), m_viewMenu( NULL ), m_metronomeToggle( 0 ), m_session( Normal ) { -#if !defined(LMMS_BUILD_WIN32) && !defined(LMMS_BUILD_APPLE) && !defined(LMMS_BUILD_HAIKU) && QT_VERSION >= 0x050000 +#if !defined(LMMS_BUILD_WIN32) && !defined(LMMS_BUILD_APPLE) && !defined(LMMS_BUILD_HAIKU) disableAutoKeyAccelerators(this); #endif setAttribute( Qt::WA_DeleteOnClose ); @@ -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 { @@ -213,7 +213,7 @@ MainWindow::MainWindow() : vbox->addWidget( w ); setCentralWidget( main_widget ); - m_updateTimer.start( 1000 / 20, this ); // 20 fps + m_updateTimer.start( 1000 / 60, this ); // 60 fps if( ConfigManager::inst()->value( "ui", "enableautosave" ).toInt() ) { @@ -266,7 +266,7 @@ MainWindow::~MainWindow() void MainWindow::finalize() { resetWindowTitle(); - setWindowIcon( embed::getIconPixmap( "icon" ) ); + setWindowIcon( embed::getIconPixmap( "icon_small" ) ); // project-popup-menu @@ -277,31 +277,21 @@ void MainWindow::finalize() this, SLOT( createNewProject() ), QKeySequence::New ); - m_templatesMenu = new QMenu( tr("New from template"), this ); - connect( m_templatesMenu, SIGNAL( aboutToShow() ), SLOT( fillTemplatesMenu() ) ); - connect( m_templatesMenu, SIGNAL( triggered( QAction * ) ), - SLOT( createNewProjectFromTemplate( QAction * ) ) ); - - project_menu->addMenu(m_templatesMenu); + auto templates_menu = new TemplatesMenu( this ); + project_menu->addMenu(templates_menu); project_menu->addAction( embed::getIconPixmap( "project_open" ), tr( "&Open..." ), this, SLOT( openProject() ), QKeySequence::Open ); - m_recentlyOpenedProjectsMenu = project_menu->addMenu( - embed::getIconPixmap( "project_open_recent" ), - tr( "&Recently Opened Projects" ) ); - connect( m_recentlyOpenedProjectsMenu, SIGNAL( aboutToShow() ), - this, SLOT( updateRecentlyOpenedProjectsMenu() ) ); - connect( m_recentlyOpenedProjectsMenu, SIGNAL( triggered( QAction * ) ), - this, SLOT( openRecentlyOpenedProject( QAction * ) ) ); + project_menu->addMenu(new RecentProjectsMenu(this)); project_menu->addAction( embed::getIconPixmap( "project_save" ), 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 ); @@ -310,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" ), @@ -336,7 +327,7 @@ void MainWindow::finalize() Qt::CTRL + Qt::Key_M ); // Prevent dangling separator at end of menu per https://bugreports.qt.io/browse/QTBUG-40071 -#if !(defined(LMMS_BUILD_APPLE) && (QT_VERSION >= 0x050000) && (QT_VERSION < 0x050600)) +#if !(defined(LMMS_BUILD_APPLE) && (QT_VERSION < 0x050600)) project_menu->addSeparator(); #endif project_menu->addAction( embed::getIconPixmap( "exit" ), tr( "&Quit" ), @@ -411,10 +402,10 @@ void MainWindow::finalize() } // Prevent dangling separator at end of menu per https://bugreports.qt.io/browse/QTBUG-40071 -#if !(defined(LMMS_BUILD_APPLE) && (QT_VERSION >= 0x050000) && (QT_VERSION < 0x050600)) +#if !(defined(LMMS_BUILD_APPLE) && (QT_VERSION < 0x050600)) help_menu->addSeparator(); #endif - help_menu->addAction( embed::getIconPixmap( "icon" ), tr( "About" ), + help_menu->addAction( embed::getIconPixmap( "icon_small" ), tr( "About" ), this, SLOT( aboutLMMS() ) ); // create tool-buttons @@ -429,7 +420,7 @@ void MainWindow::finalize() tr( "Create new project from template" ), this, SLOT( emptySlot() ), m_toolBar ); - project_new_from_template->setMenu( m_templatesMenu ); + project_new_from_template->setMenu( templates_menu ); project_new_from_template->setPopupMode( ToolButton::InstantPopup ); ToolButton * project_open = new ToolButton( @@ -443,7 +434,7 @@ void MainWindow::finalize() embed::getIconPixmap( "project_open_recent" ), tr( "Recently opened projects" ), this, SLOT( emptySlot() ), m_toolBar ); - project_open_recent->setMenu( m_recentlyOpenedProjectsMenu ); + project_open_recent->setMenu( new RecentProjectsMenu(this) ); project_open_recent->setPopupMode( ToolButton::InstantPopup ); ToolButton * project_save = new ToolButton( @@ -555,7 +546,9 @@ void MainWindow::finalize() } // look whether mixer failed to start the audio device selected by the // user and is using AudioDummy as a fallback - else if( Engine::mixer()->audioDevStartFailed() ) + // or the audio device is set to invalid one + else if( Engine::mixer()->audioDevStartFailed() || !Mixer::isAudioDevNameValid( + ConfigManager::inst()->value( "mixer", "audiodev" ) ) ) { // if so, offer the audio settings section of the setup dialog SetupDialog sd( SetupDialog::AudioSettings ); @@ -623,6 +616,7 @@ SubWindow* MainWindow::addWindowedWidget(QWidget *w, Qt::WindowFlags windowFlags SubWindow *win = new SubWindow(m_workspace->viewport(), windowFlags); win->setAttribute(Qt::WA_DeleteOnClose); win->setWidget(w); + if (w && w->sizeHint().isValid()) {win->resize(w->sizeHint());} m_workspace->addSubWindow(win); return win; } @@ -720,7 +714,7 @@ void MainWindow::clearKeyModifiers() void MainWindow::saveWidgetState( QWidget * _w, QDomElement & _de ) { - // If our widget is the main content of a window (e.g. piano roll, FxMixer, etc), + // If our widget is the main content of a window (e.g. piano roll, FxMixer, etc), // we really care about the position of the *window* - not the position of the widget within its window if( _w->parentWidget() != NULL && _w->parentWidget()->inherits( "QMdiSubWindow" ) ) @@ -728,7 +722,7 @@ void MainWindow::saveWidgetState( QWidget * _w, QDomElement & _de ) _w = _w->parentWidget(); } - // If the widget is a SubWindow, then we can make use of the getTrueNormalGeometry() method that + // If the widget is a SubWindow, then we can make use of the getTrueNormalGeometry() method that // performs the same as normalGeometry, but isn't broken on X11 ( see https://bugreports.qt.io/browse/QTBUG-256 ) SubWindow *asSubWindow = qobject_cast(_w); QRect normalGeom = asSubWindow != nullptr ? asSubWindow->getTrueNormalGeometry() : _w->normalGeometry(); @@ -757,7 +751,7 @@ void MainWindow::restoreWidgetState( QWidget * _w, const QDomElement & _de ) qMax( _w->minimumHeight(), _de.attribute( "height" ).toInt() ) ); if( _de.hasAttribute( "visible" ) && !r.isNull() ) { - // If our widget is the main content of a window (e.g. piano roll, FxMixer, etc), + // If our widget is the main content of a window (e.g. piano roll, FxMixer, etc), // we really care about the position of the *window* - not the position of the widget within its window if ( _w->parentWidget() != NULL && _w->parentWidget()->inherits( "QMdiSubWindow" ) ) @@ -767,7 +761,10 @@ void MainWindow::restoreWidgetState( QWidget * _w, const QDomElement & _de ) // first restore the window, as attempting to resize a maximized window causes graphics glitching _w->setWindowState( _w->windowState() & ~(Qt::WindowMaximized | Qt::WindowMinimized) ); - _w->resize( r.size() ); + // Check isEmpty() to work around corrupt project files with empty size + if ( ! r.size().isEmpty() ) { + _w->resize( r.size() ); + } _w->move( r.topLeft() ); // set the window to its correct minimized/maximized/restored state @@ -803,24 +800,6 @@ void MainWindow::createNewProject() -void MainWindow::createNewProjectFromTemplate( QAction * _idx ) -{ - if( m_templatesMenu && mayChangeProject(true) ) - { - int indexOfTemplate = m_templatesMenu->actions().indexOf( _idx ); - bool isFactoryTemplate = indexOfTemplate >= m_custom_templates_count; - QString dirBase = isFactoryTemplate ? - ConfigManager::inst()->factoryTemplatesDir() : - ConfigManager::inst()->userTemplateDir(); - - const QString f = dirBase + _idx->text().replace("&&", "&") + ".mpt"; - Engine::getSong()->createNewProjectFromTemplate(f); - } -} - - - - void MainWindow::openProject() { if( mayChangeProject(false) ) @@ -845,71 +824,21 @@ void MainWindow::openProject() -void MainWindow::updateRecentlyOpenedProjectsMenu() -{ - m_recentlyOpenedProjectsMenu->clear(); - QStringList rup = ConfigManager::inst()->recentlyOpenedProjects(); - -// The file history goes 50 deep but we only show the 15 -// most recent ones that we can open and omit .mpt files. - int shownInMenu = 0; - for( QStringList::iterator it = rup.begin(); it != rup.end(); ++it ) - { - QFileInfo recentFile( *it ); - if ( recentFile.exists() && - *it != ConfigManager::inst()->recoveryFile() ) - { - if( recentFile.suffix().toLower() == "mpt" ) - { - continue; - } - - m_recentlyOpenedProjectsMenu->addAction( - embed::getIconPixmap( "project_file" ), it->replace("&", "&&") ); -#ifdef LMMS_BUILD_APPLE - m_recentlyOpenedProjectsMenu->actions().last()->setIconVisibleInMenu(false); // QTBUG-44565 workaround - m_recentlyOpenedProjectsMenu->actions().last()->setIconVisibleInMenu(true); -#endif - shownInMenu++; - if( shownInMenu >= 15 ) - { - return; - } - } - } -} - - - -void MainWindow::openRecentlyOpenedProject( QAction * _action ) -{ - if ( mayChangeProject(true) ) - { - const QString f = _action->text().replace("&&", "&"); - setCursor( Qt::WaitCursor ); - Engine::getSong()->loadProject( f ); - setCursor( Qt::ArrowCursor ); - } -} - - - - bool MainWindow::saveProject() { if( Engine::getSong()->projectFileName() == "" ) { return( saveProjectAs() ); } - else + else if( this->guiSaveProject() ) { - this->guiSaveProject(); if( getSession() == Recover ) { sessionCleanup(); } + return true; } - return( true ); + return false; } @@ -917,7 +846,8 @@ bool MainWindow::saveProject() bool MainWindow::saveProjectAs() { - VersionedSaveDialog sfd( this, tr( "Save Project" ), "", + auto optionsWidget = new SaveOptionsWidget(Engine::getSong()->getSaveOptions()); + VersionedSaveDialog sfd( this, optionsWidget, tr( "Save Project" ), "", tr( "LMMS Project" ) + " (*.mmpz *.mmp);;" + tr( "LMMS Project Template" ) + " (*.mpt)" ); QString f = Engine::getSong()->projectFileName(); @@ -955,14 +885,16 @@ bool MainWindow::saveProjectAs() } } } - this->guiSaveProjectAs( fname ); - if( getSession() == Recover ) + if( this->guiSaveProjectAs( fname ) ) { - sessionCleanup(); + if( getSession() == Recover ) + { + sessionCleanup(); + } + return true; } - return( true ); } - return( false ); + return false; } @@ -980,8 +912,7 @@ bool MainWindow::saveProjectAsNewVersion() do VersionedSaveDialog::changeFileNameVersion( fileName, true ); while ( QFile( fileName ).exists() ); - this->guiSaveProjectAs( fileName ); - return true; + return this->guiSaveProjectAs( fileName ); } } @@ -1439,40 +1370,6 @@ void MainWindow::timerEvent( QTimerEvent * _te) -void MainWindow::fillTemplatesMenu() -{ - m_templatesMenu->clear(); - - auto addTemplatesFromDir = [this]( QDir dir ) { - QStringList templates = dir.entryList( QStringList( "*.mpt" ), - QDir::Files | QDir::Readable ); - - if ( templates.size() && ! m_templatesMenu->actions().isEmpty() ) - { - m_templatesMenu->addSeparator(); - } - - for( QStringList::iterator it = templates.begin(); - it != templates.end(); ++it ) - { - m_templatesMenu->addAction( - embed::getIconPixmap( "project_file" ), - ( *it ).left( ( *it ).length() - 4 ).replace("&", "&&") ); -#ifdef LMMS_BUILD_APPLE - m_templatesMenu->actions().last()->setIconVisibleInMenu(false); // QTBUG-44565 workaround - m_templatesMenu->actions().last()->setIconVisibleInMenu(true); -#endif - } - - return templates.size(); - }; - - m_custom_templates_count = addTemplatesFromDir( ConfigManager::inst()->userTemplateDir() ); - addTemplatesFromDir( ConfigManager::inst()->factoryProjectsDir() + "templates" ); -} - - - void MainWindow::showTool( QAction * _idx ) { @@ -1620,7 +1517,12 @@ void MainWindow::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, diff --git a/src/gui/MidiSetupWidget.cpp b/src/gui/MidiSetupWidget.cpp index ccde9f29e..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::Null() (distinct from QString("")) - // to indicate that there is no editable DEVICE field + // supply devName=QString() (distinct from QString("")) + // 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/PianoView.cpp b/src/gui/PianoView.cpp index 6e8464dd4..c5f1b623f 100644 --- a/src/gui/PianoView.cpp +++ b/src/gui/PianoView.cpp @@ -187,7 +187,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 @@ -355,7 +355,7 @@ int PianoView::getKeyFromMouse( const QPoint & _p ) const } // some range-checking-stuff - return tLimit( key_num, 0, NumKeys - 1 ); + return qBound( 0, key_num, NumKeys - 1 ); } diff --git a/src/gui/PluginBrowser.cpp b/src/gui/PluginBrowser.cpp index dc0fc35e0..671b58381 100644 --- a/src/gui/PluginBrowser.cpp +++ b/src/gui/PluginBrowser.cpp @@ -24,14 +24,16 @@ #include "PluginBrowser.h" +#include #include -#include +#include #include -#include +#include #include +#include #include "embed.h" -#include "templates.h" +#include "Engine.h" #include "gui_templates.h" #include "StringPairDrag.h" #include "PluginFactory.h" @@ -59,23 +61,91 @@ PluginBrowser::PluginBrowser( QWidget * _parent ) : m_view ); hint->setWordWrap( true ); - QScrollArea* scrollarea = new QScrollArea( m_view ); - PluginDescList* descList = new PluginDescList( m_view ); - scrollarea->setWidget(descList); - scrollarea->setWidgetResizable(true); + QLineEdit * searchBar = new QLineEdit( m_view ); + searchBar->setPlaceholderText( "Search" ); + searchBar->setMaxLength( 64 ); + searchBar->setClearButtonEnabled( true ); - view_layout->addWidget(hint); - view_layout->addWidget(scrollarea); + m_descTree = new QTreeWidget( m_view ); + m_descTree->setColumnCount( 1 ); + m_descTree->header()->setVisible( false ); + m_descTree->setIndentation( 10 ); + m_descTree->setSelectionMode( QAbstractItemView::NoSelection ); + + connect( searchBar, SIGNAL( textEdited( const QString & ) ), + this, SLOT( onFilterChanged( const QString & ) ) ); + + view_layout->addWidget( hint ); + view_layout->addWidget( searchBar ); + view_layout->addWidget( m_descTree ); + + // Add LMMS root to the tree + m_lmmsRoot = new QTreeWidgetItem(); + m_lmmsRoot->setText( 0, "LMMS" ); + m_descTree->insertTopLevelItem( 0, m_lmmsRoot ); + m_lmmsRoot->setExpanded( true ); + + // Add LV2 root to the tree + m_lv2Root = new QTreeWidgetItem(); + m_lv2Root->setText( 0, "LV2" ); + m_descTree->insertTopLevelItem( 1, m_lv2Root ); + + // Add plugins to the tree roots + addPlugins(); + + // Resize + m_descTree->header()->setSectionResizeMode( QHeaderView::ResizeToContents ); + + // Hide empty roots + updateRootVisibilities(); } - - -PluginDescList::PluginDescList(QWidget *parent) : - QWidget(parent) +void PluginBrowser::updateRootVisibility( int rootIndex ) { - QVBoxLayout* layout = new QVBoxLayout(this); + QTreeWidgetItem * root = m_descTree->topLevelItem( rootIndex ); + root->setHidden( !root->childCount() ); +} + +void PluginBrowser::updateRootVisibilities() +{ + int rootCount = m_descTree->topLevelItemCount(); + for (int rootIndex = 0; rootIndex < rootCount; ++rootIndex) + { + updateRootVisibility( rootIndex ); + } +} + + +void PluginBrowser::onFilterChanged( const QString & filter ) +{ + int rootCount = m_descTree->topLevelItemCount(); + for (int rootIndex = 0; rootIndex < rootCount; ++rootIndex) + { + QTreeWidgetItem * root = m_descTree->topLevelItem( rootIndex ); + + int itemCount = root->childCount(); + for (int itemIndex = 0; itemIndex < itemCount; ++itemIndex) + { + QTreeWidgetItem * item = root->child( itemIndex ); + PluginDescWidget * descWidget = static_cast + (m_descTree->itemWidget( item, 0)); + if (descWidget->name().contains(filter, Qt::CaseInsensitive)) + { + item->setHidden( false ); + } + else + { + item->setHidden( true ); + } + } + } +} + + +void PluginBrowser::addPlugins() +{ QList descs = pluginFactory->descriptors(Plugin::Instrument); std::sort( descs.begin(), @@ -85,37 +155,71 @@ PluginDescList::PluginDescList(QWidget *parent) : return qstricmp( d1->displayName, d2->displayName ) < 0 ? true : false; } ); - for (const Plugin::Descriptor* desc : descs) + + typedef Plugin::Descriptor::SubPluginFeatures::KeyList PluginKeyList; + typedef Plugin::Descriptor::SubPluginFeatures::Key PluginKey; + PluginKeyList subPluginKeys, pluginKeys; + + for (const Plugin::Descriptor* desc: descs) { - PluginDescWidget* p = new PluginDescWidget( *desc, this ); - p->show(); - layout->addWidget(p); + if ( desc->subPluginFeatures ) + { + desc->subPluginFeatures->listSubPluginKeys( + desc, + subPluginKeys ); + } + else + { + pluginKeys << PluginKey( desc, desc->name ); + } } - setLayout(layout); - layout->addStretch(); + pluginKeys += subPluginKeys; + + for (const PluginKey& key : pluginKeys) + { + QTreeWidgetItem * item = new QTreeWidgetItem(); + if ( key.desc->name == QStringLiteral("lv2instrument") ) + { + m_lv2Root->addChild( item ); + } + else + { + m_lmmsRoot->addChild( item ); + } + PluginDescWidget* p = new PluginDescWidget( key, m_descTree ); + m_descTree->setItemWidget( item, 0, p ); + } } -PluginDescWidget::PluginDescWidget( const Plugin::Descriptor & _pd, +PluginDescWidget::PluginDescWidget(const PluginKey &_pk, QWidget * _parent ) : QWidget( _parent ), - m_pluginDescriptor( _pd ), - m_logo( _pd.logo->pixmap() ), + m_pluginKey( _pk ), + m_logo( _pk.logo()->pixmap() ), m_mouseOver( false ) { setFixedHeight( DEFAULT_HEIGHT ); setMouseTracking( true ); setCursor( Qt::PointingHandCursor ); - setToolTip(_pd.description); + setToolTip(_pk.description()); } -void PluginDescWidget::paintEvent( QPaintEvent * e ) +QString PluginDescWidget::name() const +{ + return m_pluginKey.displayName(); +} + + + + +void PluginDescWidget::paintEvent( QPaintEvent * ) { QPainter p( this ); @@ -126,7 +230,7 @@ void PluginDescWidget::paintEvent( QPaintEvent * e ) style()->drawPrimitive( QStyle::PE_Widget, &o, &p, this ); // Draw the rest - const int s = 16 + ( 32 * ( tLimit( height(), 24, 60 ) - 24 ) ) / + const int s = 16 + ( 32 * ( qBound( 24, height(), 60 ) - 24 ) ) / ( 60 - 24 ); const QSize logo_size( s, s ); QPixmap logo = m_logo.scaled( logo_size, Qt::KeepAspectRatio, @@ -140,8 +244,7 @@ void PluginDescWidget::paintEvent( QPaintEvent * e ) } p.setFont( f ); - p.drawText( 10 + logo_size.width(), 15, - m_pluginDescriptor.displayName ); + p.drawText( 10 + logo_size.width(), 15, m_pluginKey.displayName()); } @@ -169,10 +272,11 @@ void PluginDescWidget::leaveEvent( QEvent * _e ) void PluginDescWidget::mousePressEvent( QMouseEvent * _me ) { - if( _me->button() == Qt::LeftButton ) + if ( _me->button() == Qt::LeftButton ) { - new StringPairDrag( "instrument", m_pluginDescriptor.name, - m_logo, this ); + Engine::setDndPluginKey(&m_pluginKey); + new StringPairDrag("instrument", + QString::fromUtf8(m_pluginKey.desc->name), m_logo, this); leaveEvent( _me ); } } 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/SetupDialog.cpp b/src/gui/SetupDialog.cpp index 2f567a869..885f43dec 100644 --- a/src/gui/SetupDialog.cpp +++ b/src/gui/SetupDialog.cpp @@ -22,6 +22,7 @@ * */ + #include #include #include @@ -30,346 +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" -inline void labelWidget( QWidget * _w, const QString & _txt ) + +constexpr int BUFFERSIZE_RESOLUTION = 32; + +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_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", "1").toInt()), + m_disableAutoQuit(ConfigManager::inst()->value( + "ui", "disableautoquit", "1").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" ).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").toInt() ), - m_vstEmbedMethod( ConfigManager::inst()->vstEmbedMethod() ) + 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, 256 ); - 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 / 64 ); - - connect( m_bufSizeSlider, SIGNAL( valueChanged( int ) ), this, - SLOT( setBufferSize( int ) ) ); - - m_bufSizeLbl = new QLabel( bufsize_tw ); - m_bufSizeLbl->setGeometry( 10, 40, 200, 24 ); - 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; + + // Main widget. + QWidget * main_w = new QWidget(this); - LedCheckBox * enable_tooltips = new LedCheckBox( - tr( "Enable tooltips" ), - misc_tw ); - labelNumber++; - enable_tooltips->move( XDelta, YDelta*labelNumber ); - enable_tooltips->setChecked( m_toolTips ); - connect( enable_tooltips, SIGNAL( toggled( bool ) ), - this, SLOT( toggleToolTips( bool ) ) ); + // 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")); - LedCheckBox * restart_msg = new LedCheckBox( - tr( "Show restart warning after changing settings" ), - misc_tw ); - labelNumber++; - restart_msg->move( XDelta, YDelta*labelNumber ); - restart_msg->setChecked( m_warnAfterSetup ); - connect( restart_msg, SIGNAL( toggled( bool ) ), - this, SLOT( toggleWarnAfterSetup( bool ) ) ); + auto addLedCheckBox = [&XDelta, &YDelta, this]( + const char* ledText, + TabWidget* tw, + int& counter, + bool initialState, + const char* toggledSlot, + bool showRestartWarning + ){ + 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())); + } + }; - LedCheckBox * dbfs = new LedCheckBox( tr( "Display volume as dBFS " ), - misc_tw ); - labelNumber++; - dbfs->move( XDelta, YDelta*labelNumber ); - dbfs->setChecked( m_displaydBFS ); - connect( dbfs, SIGNAL( toggled( bool ) ), - this, SLOT( toggleDisplaydBFS( bool ) ) ); + int counter = 0; + + // GUI tab. + TabWidget * gui_tw = new TabWidget( + tr("Graphical user interface (GUI)"), general_w); - LedCheckBox * mmpz = new LedCheckBox( - tr( "Compress project files per default" ), - misc_tw ); - labelNumber++; - mmpz->move( XDelta, YDelta*labelNumber ); - mmpz->setChecked( m_MMPZ ); - connect( mmpz, SIGNAL( toggled( bool ) ), - this, SLOT( toggleMMPZ( bool ) ) ); + 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); - LedCheckBox * oneitw = new LedCheckBox( - tr( "One instrument track window mode" ), - misc_tw ); - labelNumber++; - oneitw->move( XDelta, YDelta*labelNumber ); - oneitw->setChecked( m_oneInstrumentTrackWindow ); - connect( oneitw, SIGNAL( toggled( bool ) ), - this, SLOT( toggleOneInstrumentTrackWindow( bool ) ) ); - - LedCheckBox * hqaudio = new LedCheckBox( - tr( "HQ-mode for output audio-device" ), - misc_tw ); - labelNumber++; - hqaudio->move( XDelta, YDelta*labelNumber ); - hqaudio->setChecked( m_hqAudioDev ); - connect( hqaudio, SIGNAL( toggled( bool ) ), - this, SLOT( toggleHQAudioDev( bool ) ) ); - - LedCheckBox * compacttracks = new LedCheckBox( - tr( "Compact track buttons" ), - misc_tw ); - labelNumber++; - compacttracks->move( XDelta, YDelta*labelNumber ); - compacttracks->setChecked( m_compactTrackButtons ); - connect( compacttracks, SIGNAL( toggled( bool ) ), - this, SLOT( toggleCompactTrackButtons( bool ) ) ); + gui_tw->setFixedHeight(YDelta + YDelta * counter); - LedCheckBox * syncVST = new LedCheckBox( - tr( "Sync VST plugins to host playback" ), - misc_tw ); - labelNumber++; - syncVST->move( XDelta, YDelta*labelNumber ); - syncVST->setChecked( m_syncVSTPlugins ); - connect( syncVST, SIGNAL( toggled( bool ) ), - this, SLOT( toggleSyncVSTPlugins( bool ) ) ); + counter = 0; - LedCheckBox * noteLabels = new LedCheckBox( - tr( "Enable note labels in piano roll" ), - misc_tw ); - labelNumber++; - noteLabels->move( XDelta, YDelta*labelNumber ); - noteLabels->setChecked( m_printNoteLabels ); - connect( noteLabels, SIGNAL( toggled( bool ) ), - this, SLOT( toggleNoteLabels( bool ) ) ); + // Projects tab. + TabWidget * projects_tw = new TabWidget( + tr("Projects"), general_w); - LedCheckBox * displayWaveform = new LedCheckBox( - tr( "Enable waveform display by default" ), - misc_tw ); - labelNumber++; - displayWaveform->move( XDelta, YDelta*labelNumber ); - displayWaveform->setChecked( m_displayWaveform ); - connect( displayWaveform, SIGNAL( toggled( bool ) ), - this, SLOT( toggleDisplayWaveform( bool ) ) ); - LedCheckBox * disableAutoquit = new LedCheckBox( - tr( "Keep effects running even without input" ), - misc_tw ); - labelNumber++; - disableAutoquit->move( XDelta, YDelta*labelNumber ); - disableAutoquit->setChecked( m_disableAutoQuit ); - connect( disableAutoquit, SIGNAL( toggled( bool ) ), - this, SLOT( toggleDisableAutoquit( bool ) ) ); + 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); - LedCheckBox * disableBackup = new LedCheckBox( - tr( "Create backup file when saving a project" ), - misc_tw ); - labelNumber++; - disableBackup->move( XDelta, YDelta*labelNumber ); - disableBackup->setChecked( m_disableBackup ); - connect( disableBackup, SIGNAL( toggled( bool ) ), - this, SLOT( toggleDisableBackup( bool ) ) ); + projects_tw->setFixedHeight(YDelta + YDelta * counter); - LedCheckBox * openLastProject = new LedCheckBox( - tr( "Reopen last project on start" ), - misc_tw ); - labelNumber++; - openLastProject->move( XDelta, YDelta*labelNumber ); - openLastProject->setChecked( m_openLastProject ); - connect( openLastProject, SIGNAL( toggled( bool ) ), - this, SLOT( toggleOpenLastProject( bool ) ) ); + // 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); - misc_tw->setFixedHeight( YDelta*labelNumber + HeaderSize ); - - TabWidget* embed_tw = new TabWidget( tr( "PLUGIN EMBEDDING" ), general); - embed_tw->setFixedHeight( 48 ); - 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") ) + QDir dir(ConfigManager::inst()->localeDir()); + QStringList fileNames = dir.entryList(QStringList("*.qm")); + for(int i = 0; i < fileNames.size(); ++i) { - m_vstEmbedComboBox->addItem( tr( "Embed using Qt API" ), "qt" ); + // 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); } - 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 ) ); - 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 ) + // If language unset, fallback to system language when available. + if(m_lang == "") { - // 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; } @@ -379,607 +281,569 @@ 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; -#endif -#ifdef LMMS_HAVE_FLUIDSYNTH - pathsHeight += 55; -#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 ) ); - - - QScrollArea *pathScroll = new QScrollArea( paths ); - - 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 ); - - const int txtLength = 284; - const int btnStart = 297; - - - // working-dir - TabWidget * lmms_wd_tw = new TabWidget( tr( - "LMMS working directory" ).toUpper(), - pathSelectors ); - lmms_wd_tw->setFixedHeight( 48 ); - - m_wdLineEdit = new QLineEdit( m_workingDir, lmms_wd_tw ); - m_wdLineEdit->setGeometry( 10, 20, txtLength, 16 ); - connect( m_wdLineEdit, SIGNAL( textChanged( const QString & ) ), this, - SLOT( setWorkingDir( const QString & ) ) ); - - QPushButton * workingdir_select_btn = new QPushButton( - embed::getIconPixmap( "project_open", 16, 16 ), - "", lmms_wd_tw ); - workingdir_select_btn->setFixedSize( 24, 24 ); - workingdir_select_btn->move( btnStart, 16 ); - connect( workingdir_select_btn, SIGNAL( clicked() ), this, - SLOT( openWorkingDir() ) ); - - - // artwork-dir - TabWidget * artwork_tw = new TabWidget( tr( - "Themes directory" ).toUpper(), - pathSelectors ); - artwork_tw->setFixedHeight( 48 ); - - m_adLineEdit = new QLineEdit( m_artworkDir, artwork_tw ); - m_adLineEdit->setGeometry( 10, 20, txtLength, 16 ); - connect( m_adLineEdit, SIGNAL( textChanged( const QString & ) ), this, - SLOT( setArtworkDir( const QString & ) ) ); - - QPushButton * artworkdir_select_btn = new QPushButton( - embed::getIconPixmap( "project_open", 16, 16 ), - "", artwork_tw ); - artworkdir_select_btn->setFixedSize( 24, 24 ); - artworkdir_select_btn->move( btnStart, 16 ); - connect( artworkdir_select_btn, SIGNAL( clicked() ), this, - SLOT( openArtworkDir() ) ); - - - - // background artwork file - TabWidget * backgroundArtwork_tw = new TabWidget( tr( - "Background artwork" ).toUpper(), paths ); - backgroundArtwork_tw->setFixedHeight( 48 ); - - m_baLineEdit = new QLineEdit( m_backgroundArtwork, - backgroundArtwork_tw ); - m_baLineEdit->setGeometry( 10, 20, txtLength, 16 ); - connect( m_baLineEdit, SIGNAL( textChanged( const QString & ) ), this, - SLOT( setBackgroundArtwork( const QString & ) ) ); - - QPushButton * backgroundartworkdir_select_btn = new QPushButton( - embed::getIconPixmap( "project_open", 16, 16 ), - "", backgroundArtwork_tw ); - backgroundartworkdir_select_btn->setFixedSize( 24, 24 ); - backgroundartworkdir_select_btn->move( btnStart, 16 ); - connect( backgroundartworkdir_select_btn, SIGNAL( clicked() ), this, - SLOT( openBackgroundArtwork() ) ); - - // vst-dir - TabWidget * vst_tw = new TabWidget( tr( - "VST-plugin directory" ).toUpper(), - pathSelectors ); - vst_tw->setFixedHeight( 48 ); - - m_vdLineEdit = new QLineEdit( m_vstDir, vst_tw ); - m_vdLineEdit->setGeometry( 10, 20, txtLength, 16 ); - connect( m_vdLineEdit, SIGNAL( textChanged( const QString & ) ), this, - SLOT( setVSTDir( const QString & ) ) ); - - QPushButton * vstdir_select_btn = new QPushButton( - embed::getIconPixmap( "project_open", 16, 16 ), - "", vst_tw ); - vstdir_select_btn->setFixedSize( 24, 24 ); - vstdir_select_btn->move( btnStart, 16 ); - connect( vstdir_select_btn, SIGNAL( clicked() ), this, - SLOT( openVSTDir() ) ); - - // gig-dir - TabWidget * gig_tw = new TabWidget( tr( - "GIG directory" ).toUpper(), - pathSelectors ); - gig_tw->setFixedHeight( 48 ); - - m_gigLineEdit = new QLineEdit( m_gigDir, gig_tw ); - m_gigLineEdit->setGeometry( 10, 20, txtLength, 16 ); - connect( m_gigLineEdit, SIGNAL( textChanged( const QString & ) ), this, - SLOT( setGIGDir( const QString & ) ) ); - - QPushButton * gigdir_select_btn = new QPushButton( - embed::getIconPixmap( "project_open", 16, 16 ), - "", gig_tw ); - gigdir_select_btn->setFixedSize( 24, 24 ); - gigdir_select_btn->move( btnStart, 16 ); - connect( gigdir_select_btn, SIGNAL( clicked() ), this, - SLOT( openGIGDir() ) ); - - // sf2-dir - TabWidget * sf2_tw = new TabWidget( tr( - "SF2 directory" ).toUpper(), - pathSelectors ); - sf2_tw->setFixedHeight( 48 ); - - m_sf2LineEdit = new QLineEdit( m_sf2Dir, sf2_tw ); - m_sf2LineEdit->setGeometry( 10, 20, txtLength, 16 ); - connect( m_sf2LineEdit, SIGNAL( textChanged( const QString & ) ), this, - SLOT( setSF2Dir( const QString & ) ) ); - - QPushButton * sf2dir_select_btn = new QPushButton( - embed::getIconPixmap( "project_open", 16, 16 ), - "", sf2_tw ); - sf2dir_select_btn->setFixedSize( 24, 24 ); - sf2dir_select_btn->move( btnStart, 16 ); - connect( sf2dir_select_btn, SIGNAL( clicked() ), this, - SLOT( openSF2Dir() ) ); - - - - // LADSPA-dir - TabWidget * lad_tw = new TabWidget( tr( - "LADSPA plugin directories" ).toUpper(), - paths ); - lad_tw->setFixedHeight( 48 ); - - m_ladLineEdit = new QLineEdit( m_ladDir, lad_tw ); - m_ladLineEdit->setGeometry( 10, 20, txtLength, 16 ); - connect( m_ladLineEdit, SIGNAL( textChanged( const QString & ) ), this, - SLOT( setLADSPADir( const QString & ) ) ); - - QPushButton * laddir_select_btn = new QPushButton( - embed::getIconPixmap( "add_folder", 16, 16 ), - "", lad_tw ); - laddir_select_btn->setFixedSize( 24, 24 ); - laddir_select_btn->move( btnStart, 16 ); - connect( laddir_select_btn, SIGNAL( clicked() ), this, - SLOT( openLADSPADir() ) ); - - -#ifdef LMMS_HAVE_STK - // STK-dir - TabWidget * stk_tw = new TabWidget( tr( - "STK rawwave directory" ).toUpper(), - paths ); - stk_tw->setFixedHeight( 48 ); - - m_stkLineEdit = new QLineEdit( m_stkDir, stk_tw ); - m_stkLineEdit->setGeometry( 10, 20, txtLength, 16 ); - connect( m_stkLineEdit, SIGNAL( textChanged( const QString & ) ), this, - SLOT( setSTKDir( const QString & ) ) ); - - QPushButton * stkdir_select_btn = new QPushButton( - embed::getIconPixmap( "project_open", 16, 16 ), - "", stk_tw ); - stkdir_select_btn->setFixedSize( 24, 24 ); - stkdir_select_btn->move( btnStart, 16 ); - connect( stkdir_select_btn, SIGNAL( clicked() ), this, - SLOT( openSTKDir() ) ); -#endif - -#ifdef LMMS_HAVE_FLUIDSYNTH - // Soundfont - TabWidget * sf_tw = new TabWidget( tr( - "Default Soundfont File" ).toUpper(), paths ); - sf_tw->setFixedHeight( 48 ); - - m_sfLineEdit = new QLineEdit( m_defaultSoundfont, sf_tw ); - m_sfLineEdit->setGeometry( 10, 20, txtLength, 16 ); - connect( m_sfLineEdit, SIGNAL( textChanged( const QString & ) ), this, - SLOT( setDefaultSoundfont( const QString & ) ) ); - - QPushButton * sf_select_btn = new QPushButton( - embed::getIconPixmap( "project_open", 16, 16 ), - "", sf_tw ); - sf_select_btn->setFixedSize( 24, 24 ); - sf_select_btn->move( btnStart, 16 ); - connect( sf_select_btn, SIGNAL( clicked() ), this, - SLOT( openDefaultSoundfont() ) ); -#endif - - pathSelectors->setLayout( pathSelectorLayout ); - - pathSelectorLayout->addWidget( lmms_wd_tw ); - pathSelectorLayout->addSpacing( 10 ); - pathSelectorLayout->addWidget( gig_tw ); - pathSelectorLayout->addSpacing( 10 ); - pathSelectorLayout->addWidget( sf2_tw ); - pathSelectorLayout->addSpacing( 10 ); - pathSelectorLayout->addWidget( vst_tw ); - pathSelectorLayout->addSpacing( 10 ); - pathSelectorLayout->addWidget( lad_tw ); -#ifdef LMMS_HAVE_STK - pathSelectorLayout->addSpacing( 10 ); - pathSelectorLayout->addWidget( stk_tw ); -#endif -#ifdef LMMS_HAVE_FLUIDSYNTH - pathSelectorLayout->addSpacing( 10 ); - pathSelectorLayout->addWidget( sf_tw ); -#endif - pathSelectorLayout->addSpacing( 10 ); - pathSelectorLayout->addWidget( artwork_tw ); - pathSelectorLayout->addSpacing( 10 ); - pathSelectorLayout->addStretch(); - pathSelectorLayout->addWidget( backgroundArtwork_tw ); - pathSelectorLayout->addSpacing( 10 ); - - 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" ) ); + + // 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( "Auto save" ).toUpper(), performance ); - auto_save_tw->setFixedHeight( 110 ); + tr("Autosave"), performance_w); + auto_save_tw->setFixedHeight(106); - 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 ); + 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 ) ) ); + 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_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 ) ) ); + 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 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 ) ) ); + 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() ) ); - ToolTip::add( autoSaveResetBtn, tr( "Reset to default value" ) ); + 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 ); + m_saveIntervalSlider->setEnabled(m_enableAutoSave); + m_runningAutoSave->setVisible(m_enableAutoSave); - perf_layout->addWidget( auto_save_tw ); - perf_layout->addSpacing( 10 ); + 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); - TabWidget * ui_fx_tw = new TabWidget( tr( "UI effects vs. " - "performance" ).toUpper(), - performance ); - ui_fx_tw->setFixedHeight( 70 ); + counter = 0; - 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 ) ) ); + // Plugins tab. + TabWidget * plugins_tw = new TabWidget( + tr("Plugins"), performance_w); - 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 ) ) ); + 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(); - perf_layout->addWidget( ui_fx_tw ); - perf_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); - 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 ); + 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( asw ); + m_audioIfaceSetupWidgets[AudioJack::name()] = + new AudioJack::setupWidget(as_w); #endif #ifdef LMMS_HAVE_ALSA m_audioIfaceSetupWidgets[AudioAlsa::name()] = - new AudioAlsaSetupWidget( asw ); + new AudioAlsaSetupWidget(as_w); #endif #ifdef LMMS_HAVE_PULSEAUDIO m_audioIfaceSetupWidgets[AudioPulseAudio::name()] = - new AudioPulseAudio::setupWidget( asw ); + new AudioPulseAudio::setupWidget(as_w); #endif #ifdef LMMS_HAVE_PORTAUDIO m_audioIfaceSetupWidgets[AudioPortAudio::name()] = - new AudioPortAudio::setupWidget( asw ); + new AudioPortAudio::setupWidget(as_w); #endif #ifdef LMMS_HAVE_SOUNDIO m_audioIfaceSetupWidgets[AudioSoundIo::name()] = - new AudioSoundIo::setupWidget( asw ); + new AudioSoundIo::setupWidget(as_w); #endif #ifdef LMMS_HAVE_SDL m_audioIfaceSetupWidgets[AudioSdl::name()] = - new AudioSdl::setupWidget( asw ); + new AudioSdl::setupWidget(as_w); #endif #ifdef LMMS_HAVE_OSS m_audioIfaceSetupWidgets[AudioOss::name()] = - new AudioOss::setupWidget( asw ); + new AudioOss::setupWidget(as_w); #endif #ifdef LMMS_HAVE_SNDIO m_audioIfaceSetupWidgets[AudioSndio::name()] = - new AudioSndio::setupWidget( asw ); + new AudioSndio::setupWidget(as_w); #endif + m_audioIfaceSetupWidgets[AudioDummy::name()] = - new AudioDummy::setupWidget( asw ); + new AudioDummy::setupWidget(as_w); - for( AswMap::iterator it = m_audioIfaceSetupWidgets.begin(); - it != m_audioIfaceSetupWidgets.end(); ++it ) + for(AswMap::iterator it = m_audioIfaceSetupWidgets.begin(); + it != m_audioIfaceSetupWidgets.end(); ++it) { - m_audioIfaceNames[tr( it.key().toLatin1())] = it.key(); + m_audioIfaceNames[ + tr(it.key().toLatin1())] = it.key(); } - for( trMap::iterator it = m_audioIfaceNames.begin(); - it != m_audioIfaceNames.end(); ++it ) + 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() ); + as_w_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( audioDevName.length() == 0 ) + // 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 ); + ConfigManager::inst()->setValue("mixer", "audiodev", audioDevName); } m_audioInterfaces-> - setCurrentIndex( m_audioInterfaces->findText( audioDevName ) ); + setCurrentIndex(m_audioInterfaces->findText(audioDevName)); m_audioIfaceSetupWidgets[audioDevName]->show(); - connect( m_audioInterfaces, SIGNAL( activated( const QString & ) ), - this, SLOT( audioInterfaceChanged( const QString & ) ) ); + 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))); - audio_layout->addWidget( audioiface_tw ); - audio_layout->addSpacing( 20 ); - audio_layout->addWidget( asw ); + // 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(); - QWidget * midi = new QWidget( ws ); - QVBoxLayout * midi_layout = new QVBoxLayout( midi ); - midi_layout->setSpacing( 0 ); - midi_layout->setMargin( 0 ); - labelWidget( midi, tr( "MIDI settings" ) ); + // 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")); - TabWidget * midiiface_tw = new TabWidget( tr( "MIDI INTERFACE" ), - midi ); - midiiface_tw->setFixedHeight( 60 ); + // 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, 22 ); + 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); - // 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 ); + 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( msw ); + MidiSetupWidget::create(ms_w); m_midiIfaceSetupWidgets[MidiAlsaRaw::name()] = - MidiSetupWidget::create( msw ); + MidiSetupWidget::create(ms_w); #endif #ifdef LMMS_HAVE_JACK m_midiIfaceSetupWidgets[MidiJack::name()] = - MidiSetupWidget::create( msw ); + MidiSetupWidget::create(ms_w); #endif #ifdef LMMS_HAVE_OSS m_midiIfaceSetupWidgets[MidiOss::name()] = - MidiSetupWidget::create( msw ); + MidiSetupWidget::create(ms_w); #endif #ifdef LMMS_HAVE_SNDIO m_midiIfaceSetupWidgets[MidiSndio::name()] = - MidiSetupWidget::create( msw ); + MidiSetupWidget::create(ms_w); #endif #ifdef LMMS_BUILD_WIN32 m_midiIfaceSetupWidgets[MidiWinMM::name()] = - MidiSetupWidget::create( msw ); + MidiSetupWidget::create(ms_w); #endif #ifdef LMMS_BUILD_APPLE m_midiIfaceSetupWidgets[MidiApple::name()] = - MidiSetupWidget::create( msw ); + MidiSetupWidget::create(ms_w); #endif m_midiIfaceSetupWidgets[MidiDummy::name()] = - MidiSetupWidget::create( msw ); + MidiSetupWidget::create(ms_w); - for( MswMap::iterator it = m_midiIfaceSetupWidgets.begin(); - it != m_midiIfaceSetupWidgets.end(); ++it ) + for(MswMap::iterator it = m_midiIfaceSetupWidgets.begin(); + it != m_midiIfaceSetupWidgets.end(); ++it) { - m_midiIfaceNames[tr( it.key().toLatin1())] = it.key(); + m_midiIfaceNames[ + tr(it.key().toLatin1())] = it.key(); } - for( trMap::iterator it = m_midiIfaceNames.begin(); - it != m_midiIfaceNames.end(); ++it ) + 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() ); + ms_w_layout->addWidget(midiWidget); + m_midiInterfaces->addItem(it.key()); } - QString midiDevName = - ConfigManager::inst()->value( "mixer", "mididev" ); - if( midiDevName.length() == 0 ) + QString midiDevName = ConfigManager::inst()->value("mixer", "mididev"); + if (m_midiInterfaces->findText(midiDevName) < 0) { midiDevName = Engine::mixer()->midiClientName(); - ConfigManager::inst()->setValue( - "mixer", "mididev", midiDevName ); + ConfigManager::inst()->setValue("mixer", "mididev", midiDevName); } - m_midiInterfaces->setCurrentIndex( - m_midiInterfaces->findText( midiDevName ) ); + m_midiInterfaces->setCurrentIndex(m_midiInterfaces->findText(midiDevName)); m_midiIfaceSetupWidgets[midiDevName]->show(); - connect( m_midiInterfaces, SIGNAL( activated( const QString & ) ), - this, SLOT( midiInterfaceChanged( const QString & ) ) ); + 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 ordering. + midi_layout->addWidget(midiiface_tw); + midi_layout->addWidget(ms_w); 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" ) ); + + // 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")); - m_tabBar->setActiveTab( _tab_to_open ); + // Paths scroll area. + QScrollArea * pathsScroll = new QScrollArea(paths_w); + pathsScroll->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); + pathsScroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - hlayout->addWidget( m_tabBar ); - hlayout->addSpacing( 10 ); - hlayout->addWidget( ws ); - hlayout->addSpacing( 10 ); - hlayout->addStretch(); + // Path selectors widget. + QWidget * pathSelectors = new QWidget(paths_w); - 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() ) ); + const int txtLength = 284; + const int btnStart = 300; - QPushButton * cancel_btn = new QPushButton( embed::getIconPixmap( - "cancel" ), - tr( "Cancel" ), - buttons ); - connect( cancel_btn, SIGNAL( clicked() ), this, SLOT( reject() ) ); + // Path selectors layout. + QVBoxLayout * pathSelectorsLayout = new QVBoxLayout; + pathSelectorsLayout->setSpacing(10); - 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 ); + auto addPathEntry = [&](const char* caption, + const QString& content, + const char* setSlot, + const char* openSlot, + QLineEdit*& lineEdit, + const char* pixmap = "project_open") + { + TabWidget * newTw = new TabWidget(tr(caption), + pathSelectors); + newTw->setFixedHeight(48); - vlayout->addWidget( settings ); - vlayout->addSpacing( 10 ); - vlayout->addWidget( buttons ); - vlayout->addSpacing( 10 ); - vlayout->addStretch(); + lineEdit = new QLineEdit(content, newTw); + lineEdit->setGeometry(10, 20, txtLength, 16); + connect(lineEdit, SIGNAL(textChanged(const QString &)), + this, setSlot); + + QPushButton * selectBtn = new QPushButton( + embed::getIconPixmap(pixmap, 16, 16), + "", newTw); + selectBtn->setFixedSize(24, 24); + selectBtn->move(btnStart, 16); + connect(selectBtn, SIGNAL(clicked()), this, openSlot); + + pathSelectorsLayout->addWidget(newTw); + pathSelectorsLayout->addSpacing(10); + }; + + addPathEntry("LMMS working directory", m_workingDir, + SLOT(setWorkingDir(const QString &)), + SLOT(openWorkingDir()), + 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_sf2DirLineEdit); +#ifdef LMMS_HAVE_FLUIDSYNTH + addPathEntry("Default SF2", m_sf2File, + SLOT(setSF2File(const QString &)), + SLOT(openSF2File()), + m_sf2FileLineEdit); +#endif + 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(); - - } @@ -987,7 +851,7 @@ SetupDialog::SetupDialog( ConfigTabs _tab_to_open ) : SetupDialog::~SetupDialog() { - Engine::projectJournal()->setJournalling( true ); + Engine::projectJournal()->setJournalling(true); } @@ -995,272 +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( "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", -#if QT_VERSION >= 0x050000 - m_vstEmbedComboBox->currentData().toString() ); -#else - m_vstEmbedComboBox->itemData(m_vstEmbedComboBox->currentIndex()).toString() ); -#endif + 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 / 64; - 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 * 64; - 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 / 64 ); + 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::setLanguage( int lang ) +void SetupDialog::setLanguage(int lang) { m_lang = m_languages[lang]; } @@ -1268,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 != QString::null ) - { - m_wdLineEdit->setText( new_dir ); - } -} - -void SetupDialog::openGIGDir() -{ - QString new_dir = FileDialog::getExistingDirectory( this, - tr( "Choose your GIG directory" ), - m_gigDir ); - if( new_dir != QString::null ) - { - m_gigLineEdit->setText( new_dir ); - } -} - -void SetupDialog::openSF2Dir() -{ - QString new_dir = FileDialog::getExistingDirectory( this, - tr( "Choose your SF2 directory" ), - m_sf2Dir ); - if( new_dir != QString::null ) - { - 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 != QString::null ) - { - 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 != QString::null ) - { - 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 != QString::null ) - { - 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 != QString::null ) - { - 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 != QString::null ) - { - 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 != QString::null ) - { - 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(); } diff --git a/src/gui/StringPairDrag.cpp b/src/gui/StringPairDrag.cpp index a10d31c5c..b2b3b0c4a 100644 --- a/src/gui/StringPairDrag.cpp +++ b/src/gui/StringPairDrag.cpp @@ -40,7 +40,7 @@ StringPairDrag::StringPairDrag( const QString & _key, const QString & _value, { if( _icon.isNull() && _w ) { - setPixmap( QPixmap::grabWidget( _w ).scaled( + setPixmap( _w->grab().scaled( 64, 64, Qt::KeepAspectRatio, Qt::SmoothTransformation ) ); @@ -53,7 +53,7 @@ StringPairDrag::StringPairDrag( const QString & _key, const QString & _value, QMimeData * m = new QMimeData(); m->setData( mimeType(), txt.toUtf8() ); setMimeData( m ); - start( Qt::IgnoreAction ); + exec( Qt::LinkAction, Qt::LinkAction ); } diff --git a/src/gui/SubWindow.cpp b/src/gui/SubWindow.cpp index 0abe22558..5cbac4cd6 100644 --- a/src/gui/SubWindow.cpp +++ b/src/gui/SubWindow.cpp @@ -1,4 +1,4 @@ -/* +/* * SubWindow.cpp - Implementation of QMdiSubWindow that correctly tracks * the geometry that windows should be restored to. * Workaround for https://bugreports.qt.io/browse/QTBUG-256 @@ -30,6 +30,7 @@ #include #include +#include #include #include "embed.h" @@ -52,7 +53,7 @@ SubWindow::SubWindow( QWidget *parent, Qt::WindowFlags windowFlags ) : m_borderColor = Qt::black; // close, maximize and restore (after maximizing) buttons - m_closeBtn = new QPushButton( embed::getIconPixmap( "close" ), QString::null, this ); + m_closeBtn = new QPushButton( embed::getIconPixmap( "close" ), QString(), this ); m_closeBtn->resize( m_buttonSize ); m_closeBtn->setFocusPolicy( Qt::NoFocus ); m_closeBtn->setCursor( Qt::ArrowCursor ); @@ -60,7 +61,7 @@ SubWindow::SubWindow( QWidget *parent, Qt::WindowFlags windowFlags ) : m_closeBtn->setToolTip( tr( "Close" ) ); connect( m_closeBtn, SIGNAL( clicked( bool ) ), this, SLOT( close() ) ); - m_maximizeBtn = new QPushButton( embed::getIconPixmap( "maximize" ), QString::null, this ); + m_maximizeBtn = new QPushButton( embed::getIconPixmap( "maximize" ), QString(), this ); m_maximizeBtn->resize( m_buttonSize ); m_maximizeBtn->setFocusPolicy( Qt::NoFocus ); m_maximizeBtn->setCursor( Qt::ArrowCursor ); @@ -68,7 +69,7 @@ SubWindow::SubWindow( QWidget *parent, Qt::WindowFlags windowFlags ) : m_maximizeBtn->setToolTip( tr( "Maximize" ) ); connect( m_maximizeBtn, SIGNAL( clicked( bool ) ), this, SLOT( showMaximized() ) ); - m_restoreBtn = new QPushButton( embed::getIconPixmap( "restore" ), QString::null, this ); + m_restoreBtn = new QPushButton( embed::getIconPixmap( "restore" ), QString(), this ); m_restoreBtn->resize( m_buttonSize ); m_restoreBtn->setFocusPolicy( Qt::NoFocus ); m_restoreBtn->setCursor( Qt::ArrowCursor ); @@ -123,8 +124,11 @@ void SubWindow::paintEvent( QPaintEvent * ) p.drawLine( width() - 1, m_titleBarHeight, width() - 1, height() - 1 ); // window icon - QPixmap winicon( widget()->windowIcon().pixmap( m_buttonSize ) ); - p.drawPixmap( 3, 3, m_buttonSize.width(), m_buttonSize.height(), winicon ); + if( widget() ) + { + QPixmap winicon( widget()->windowIcon().pixmap( m_buttonSize ) ); + p.drawPixmap( 3, 3, m_buttonSize.width(), m_buttonSize.height(), winicon ); + } } @@ -171,32 +175,6 @@ void SubWindow::elideText( QLabel *label, QString text ) -/** - * @brief SubWindow::isMaximized - * - * This function checks if the subwindow is maximized. - * QMdiSubWindow::isMaximized() doesn't work on MacOS. - * Therefore we need our own implementation for checking this - * @return true if the subwindow is maximized at the moment. - * false if it's not. - */ -bool SubWindow::isMaximized() -{ -#ifdef LMMS_BUILD_APPLE - // check if subwindow size is identical to the MdiArea size, accounting for scrollbars - int hScrollBarHeight = mdiArea()->horizontalScrollBar()->isVisible() ? mdiArea()->horizontalScrollBar()->size().height() : 0; - int vScrollBarWidth = mdiArea()->verticalScrollBar()->isVisible() ? mdiArea()->verticalScrollBar()->size().width() : 0; - QSize areaSize( this->mdiArea()->size().width() - vScrollBarWidth, this->mdiArea()->size().height() - hScrollBarHeight ); - - return areaSize == this->size(); -#else - return QMdiSubWindow::isMaximized(); -#endif -} - - - - /** * @brief SubWindow::getTrueNormalGeometry * @@ -324,25 +302,31 @@ void SubWindow::adjustTitleBar() // we're keeping the restore button around if we open projects // from older versions that have saved minimized windows m_restoreBtn->setVisible( isMaximized() || isMinimized() ); - - // title QLabel adjustments - m_windowTitle->setAlignment( Qt::AlignHCenter ); - m_windowTitle->setFixedWidth( widget()->width() - ( menuButtonSpace + buttonBarWidth ) ); - m_windowTitle->move( menuButtonSpace, - ( m_titleBarHeight / 2 ) - ( m_windowTitle->sizeHint().height() / 2 ) - 1 ); - - // if minimized we can't use widget()->width(). We have to hard code the width, - // as the width of all minimized windows is the same. if( isMinimized() ) { m_restoreBtn->move( m_maximizeBtn->isHidden() ? middleButtonPos : leftButtonPos ); - m_windowTitle->setFixedWidth( 120 ); } - // truncate the label string if the window is to small. Adds "..." - elideText( m_windowTitle, widget()->windowTitle() ); - m_windowTitle->setTextInteractionFlags( Qt::NoTextInteraction ); - m_windowTitle->adjustSize(); + if( widget() ) + { + // title QLabel adjustments + m_windowTitle->setAlignment( Qt::AlignHCenter ); + m_windowTitle->setFixedWidth( widget()->width() - ( menuButtonSpace + buttonBarWidth ) ); + m_windowTitle->move( menuButtonSpace, + ( m_titleBarHeight / 2 ) - ( m_windowTitle->sizeHint().height() / 2 ) - 1 ); + + // if minimized we can't use widget()->width(). We have to hard code the width, + // as the width of all minimized windows is the same. + if( isMinimized() ) + { + m_windowTitle->setFixedWidth( 120 ); + } + + // truncate the label string if the window is to small. Adds "..." + elideText( m_windowTitle, widget()->windowTitle() ); + m_windowTitle->setTextInteractionFlags( Qt::NoTextInteraction ); + m_windowTitle->adjustSize(); + } } @@ -366,10 +350,10 @@ void SubWindow::focusChanged( QMdiSubWindow *subWindow ) /** * @brief SubWindow::resizeEvent * - * On every rezise event we have to adjust our title label. - * - * At next we give the event to QMdiSubWindow::resizeEvent() which handles + * At first we give the event to QMdiSubWindow::resizeEvent() which handles * the event on its behavior. + * + * On every resize event we have to adjust our title label. * * At last we store the current size into m_trackedNormalGeom. This size * will be saved with the project because of an Qt bug wich doesn't @@ -379,8 +363,11 @@ void SubWindow::focusChanged( QMdiSubWindow *subWindow ) */ void SubWindow::resizeEvent( QResizeEvent * event ) { - adjustTitleBar(); + // When the parent QMdiArea gets resized, maximized subwindows also gets resized, if any. + // In that case, we should call QMdiSubWindow::resizeEvent first + // to ensure we get the correct window state. QMdiSubWindow::resizeEvent( event ); + adjustTitleBar(); // if the window was resized and ISN'T minimized/maximized/fullscreen, // then save the current size diff --git a/src/gui/TimeLineWidget.cpp b/src/gui/TimeLineWidget.cpp index ccf32add1..bd196de7f 100644 --- a/src/gui/TimeLineWidget.cpp +++ b/src/gui/TimeLineWidget.cpp @@ -2,7 +2,7 @@ * TimeLineWidget.cpp - class timeLine, representing a time-line with position marker * * Copyright (c) 2004-2014 Tobias Doerffel - * + * * This file is part of LMMS - https://lmms.io * * This program is free software; you can redistribute it and/or @@ -40,14 +40,9 @@ #include "SongEditor.h" -#if QT_VERSION < 0x040800 -#define MiddleButton MidButton -#endif - - 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 ), @@ -66,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 ), @@ -76,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 ) { @@ -89,12 +84,13 @@ TimeLineWidget::TimeLineWidget( const int xoff, const int yoff, const float ppt, m_xOffset -= s_posMarkerPixmap->width() / 2; + setMouseTracking(true); m_pos.m_timeLine = this; QTimer * updateTimer = new QTimer( this ); connect( updateTimer, SIGNAL( timeout() ), this, SLOT( updatePosition() ) ); - updateTimer->start( 50 ); + updateTimer->start( 1000 / 60 ); // 60 fps connect( Engine::getSong(), SIGNAL( timeSignatureChanged( int,int ) ), this, SLOT( update() ) ); } @@ -251,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 ); @@ -314,50 +310,36 @@ void TimeLineWidget::mousePressEvent( QMouseEvent* event ) m_action = SelectSongTCO; m_initalXSelect = event->x(); } - else if( event->button() == Qt::RightButton || event->button() == Qt::MiddleButton ) + else if( event->button() == Qt::RightButton ) { - m_moveXOff = s_posMarkerPixmap->width() / 2; - const MidiTime t = m_begin + static_cast( event->x() * MidiTime::ticksPerTact() / m_ppt ); + m_moveXOff = s_posMarkerPixmap->width() / 2; + 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 ) + { + m_action = MoveLoopBegin; + } + else if( t > loopMid ) + { + m_action = MoveLoopEnd; + } + if( m_loopPos[0] > m_loopPos[1] ) { qSwap( m_loopPos[0], m_loopPos[1] ); } - if( ( event->modifiers() & Qt::ShiftModifier ) || event->button() == Qt::MiddleButton ) - { - m_action = MoveLoopBegin; - } - else - { - m_action = MoveLoopEnd; - } + m_loopPos[( m_action == MoveLoopBegin ) ? 0 : 1] = t; } - if( m_action == MoveLoopBegin ) + if( m_action == MoveLoopBegin || m_action == MoveLoopEnd ) { delete m_hint; m_hint = TextFloat::displayMessage( tr( "Hint" ), - tr( "Press <%1> to disable magnetic loop points." ).arg( - #ifdef LMMS_BUILD_APPLE - "⌘"), - #else - "Ctrl"), - #endif + tr( "Press <%1> to disable magnetic loop points." ).arg(UI_CTRL_KEY), embed::getIconPixmap( "hint" ), 0 ); } - else if( m_action == MoveLoopEnd ) - { - delete m_hint; - m_hint = TextFloat::displayMessage( tr( "Hint" ), - tr( "Hold to move the begin loop point; Press <%1> to disable magnetic loop points." ).arg( - #ifdef LMMS_BUILD_APPLE - "⌘"), - #else - "Ctrl"), - #endif - embed::getIconPixmap( "hint" ), 0 ); - } - mouseMoveEvent( event ); } @@ -366,7 +348,8 @@ void TimeLineWidget::mousePressEvent( QMouseEvent* event ) void TimeLineWidget::mouseMoveEvent( QMouseEvent* event ) { - const MidiTime t = m_begin + static_cast( qMax( event->x() - m_xOffset - m_moveXOff, 0 ) * MidiTime::ticksPerTact() / m_ppt ); + 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::ticksPerBar() / m_ppb ); switch( m_action ) { @@ -379,6 +362,7 @@ void TimeLineWidget::mouseMoveEvent( QMouseEvent* event ) Engine::getSong()->setToTime(t, Song::Mode_None); } m_pos.setCurrentFrame( 0 ); + m_pos.setJumped( true ); updatePosition(); positionMarkerMoved(); break; @@ -386,7 +370,7 @@ void TimeLineWidget::mouseMoveEvent( QMouseEvent* event ) case MoveLoopBegin: case MoveLoopEnd: { - const int i = m_action - MoveLoopBegin; + const int i = m_action - MoveLoopBegin; // i == 0 || i == 1 if( event->modifiers() & Qt::ControlModifier ) { // no ctrl-press-hint when having ctrl pressed @@ -396,7 +380,7 @@ void TimeLineWidget::mouseMoveEvent( QMouseEvent* event ) } else { - m_loopPos[i] = t.toNearestTact(); + m_loopPos[i] = t.quantize(1.0); } // Catch begin == end if( m_loopPos[0] == m_loopPos[1] ) @@ -404,9 +388,13 @@ 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(); + { + 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 2772ef104..9b51c76f2 100644 --- a/src/gui/TrackContainerView.cpp +++ b/src/gui/TrackContainerView.cpp @@ -54,9 +54,8 @@ TrackContainerView::TrackContainerView( TrackContainer * _tc ) : m_tc( _tc ), m_trackViews(), m_scrollArea( new scrollArea( this ) ), - m_ppt( DEFAULT_PIXELS_PER_TACT ), - m_rubberBand( new RubberBand( m_scrollArea ) ), - m_origin() + m_ppb( DEFAULT_PIXELS_PER_BAR ), + m_rubberBand( new RubberBand( m_scrollArea ) ) { m_tc->setHook( this ); //keeps the direction of the widget, undepended on the locale @@ -226,10 +225,9 @@ void TrackContainerView::scrollToTrackView( TrackView * _tv ) void TrackContainerView::realignTracks() { - QWidget * content = m_scrollArea->widget(); - content->setFixedWidth( width() - - m_scrollArea->verticalScrollBar()->width() ); - content->setFixedHeight( content->minimumSizeHint().height() ); + m_scrollArea->widget()->setFixedWidth(width()); + m_scrollArea->widget()->setFixedHeight( + m_scrollArea->widget()->minimumSizeHint().height()); for( trackViewList::iterator it = m_trackViews.begin(); it != m_trackViews.end(); ++it ) @@ -307,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(); @@ -346,12 +344,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() { @@ -384,8 +378,9 @@ void TrackContainerView::dropEvent( QDropEvent * _de ) InstrumentTrack * it = dynamic_cast( Track::create( Track::InstrumentTrack, m_tc ) ); - Instrument * i = it->loadInstrument( - pluginFactory->pluginSupportingExtension(FileItem::extension(value)).name()); + PluginFactory::PluginInfoAndKey piakn = + pluginFactory->pluginSupportingExtension(FileItem::extension(value)); + Instrument * i = it->loadInstrument(piakn.info.name(), &piakn.key); i->loadFile( value ); //it->toggledInstrumentTrackButton( true ); _de->accept(); @@ -427,55 +422,18 @@ 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(); QWidget::resizeEvent( _re ); } + + + RubberBand *TrackContainerView::rubberBand() const { - return m_rubberBand; + return m_rubberBand; } @@ -487,7 +445,6 @@ TrackContainerView::scrollArea::scrollArea( TrackContainerView * _parent ) : { setFrameStyle( QFrame::NoFrame ); setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff ); - setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOn ); } @@ -529,7 +486,8 @@ InstrumentLoaderThread::InstrumentLoaderThread( QObject *parent, InstrumentTrack void InstrumentLoaderThread::run() { - Instrument *i = m_it->loadInstrument( m_name ); + Instrument *i = m_it->loadInstrument(m_name, nullptr, + true /*always DnD*/); QObject *parent = i->parent(); i->setParent( 0 ); i->moveToThread( m_containerThread ); diff --git a/src/gui/dialogs/FileDialog.cpp b/src/gui/dialogs/FileDialog.cpp index fb9c7faac..54cc9d6e4 100644 --- a/src/gui/dialogs/FileDialog.cpp +++ b/src/gui/dialogs/FileDialog.cpp @@ -35,7 +35,7 @@ FileDialog::FileDialog( QWidget *parent, const QString &caption, const QString &directory, const QString &filter ) : QFileDialog( parent, caption, directory, filter ) { -#if (QT_VERSION >= 0x040806 && QT_VERSION < 0x050000) || QT_VERSION > 0x050200 +#if QT_VERSION > 0x050200 setOption( QFileDialog::DontUseCustomDirectoryIcons ); #endif @@ -43,27 +43,15 @@ FileDialog::FileDialog( QWidget *parent, const QString &caption, // Add additional locations to the sidebar QList urls = sidebarUrls(); -#if QT_VERSION >= 0x050000 urls << QUrl::fromLocalFile( QStandardPaths::writableLocation( QStandardPaths::DesktopLocation ) ); -#else - urls << QUrl::fromLocalFile( QDesktopServices::storageLocation( QDesktopServices::DesktopLocation ) ); -#endif // Find downloads directory QDir downloadDir( QDir::homePath() + "/Downloads" ); if ( ! downloadDir.exists() ) -#if QT_VERSION >= 0x050000 - downloadDir = QStandardPaths::writableLocation( QStandardPaths::DownloadLocation ); -#else - downloadDir = QDesktopServices::storageLocation( QDesktopServices::DocumentsLocation ) + "/Downloads"; -#endif + downloadDir.setPath(QStandardPaths::writableLocation( QStandardPaths::DownloadLocation )); if ( downloadDir.exists() ) urls << QUrl::fromLocalFile( downloadDir.absolutePath() ); -#if QT_VERSION >= 0x050000 urls << QUrl::fromLocalFile( QStandardPaths::writableLocation( QStandardPaths::MusicLocation ) ); -#else - urls << QUrl::fromLocalFile( QDesktopServices::storageLocation( QDesktopServices::MusicLocation ) ); -#endif urls << QUrl::fromLocalFile( ConfigManager::inst()->workingDir() ); // Add `/Volumes` directory on OS X systems, this allows the user to browse diff --git a/src/gui/dialogs/VersionedSaveDialog.cpp b/src/gui/dialogs/VersionedSaveDialog.cpp index e2acff590..18993c23b 100644 --- a/src/gui/dialogs/VersionedSaveDialog.cpp +++ b/src/gui/dialogs/VersionedSaveDialog.cpp @@ -28,13 +28,15 @@ #include #include #include +#include +#include #include "VersionedSaveDialog.h" - - +#include "LedCheckbox.h" VersionedSaveDialog::VersionedSaveDialog( QWidget *parent, + QWidget *saveOptionsWidget, const QString &caption, const QString &directory, const QString &filter ) : @@ -63,6 +65,17 @@ VersionedSaveDialog::VersionedSaveDialog( QWidget *parent, hLayout->addWidget( minusButton ); layout->addLayout( hLayout, 2, 1 ); + if (saveOptionsWidget) { + auto groupBox = new QGroupBox(tr("Save Options")); + auto optionsLayout = new QGridLayout; + + optionsLayout->addWidget(saveOptionsWidget, 0, 0, Qt::AlignLeft); + + groupBox->setLayout(optionsLayout); + + layout->addWidget(groupBox, layout->rowCount() + 1, 0, 1, -1); + } + // Connect + and - buttons connect( plusButton, SIGNAL( clicked() ), this, SLOT( incrementVersion() )); connect( minusButton, SIGNAL( clicked() ), this, SLOT( decrementVersion() )); @@ -160,3 +173,14 @@ bool VersionedSaveDialog::fileExistsQuery( QString FileName, QString WindowTitle } return fileExists; } + +SaveOptionsWidget::SaveOptionsWidget(Song::SaveOptions &saveOptions) { + auto *layout = new QVBoxLayout(); + + m_discardMIDIConnectionsCheckbox = new LedCheckBox(nullptr); + m_discardMIDIConnectionsCheckbox->setText(tr("Discard MIDI connections")); + m_discardMIDIConnectionsCheckbox->setModel(&saveOptions.discardMIDIConnections); + layout->addWidget(m_discardMIDIConnectionsCheckbox); + + setLayout(layout); +} diff --git a/src/gui/dialogs/export_project.ui b/src/gui/dialogs/export_project.ui index 1ec4fe123..6b175de78 100644 --- a/src/gui/dialogs/export_project.ui +++ b/src/gui/dialogs/export_project.ui @@ -7,19 +7,19 @@ 0 0 379 - 374 + 400 379 - 374 + 400 379 - 374 + 400 @@ -40,6 +40,47 @@ + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Render Looped Section: + + + + + + + time(s) + + + 1 + + + 99 + + + 1 + + + + + + diff --git a/src/gui/editors/AutomationEditor.cpp b/src/gui/editors/AutomationEditor.cpp index 890bb2346..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, @@ -198,6 +198,8 @@ AutomationEditor::AutomationEditor() : setCurrentPattern( NULL ); setMouseTracking( true ); + setFocusPolicy( Qt::StrongFocus ); + setFocus(); } @@ -405,6 +407,7 @@ void AutomationEditor::keyPressEvent(QKeyEvent * ke ) } break; + case Qt::Key_Backspace: case Qt::Key_Delete: deleteSelectedValues(); ke->accept(); @@ -430,8 +433,8 @@ void AutomationEditor::leaveEvent(QEvent * e ) { QApplication::restoreOverrideCursor(); } - QWidget::leaveEvent( e ); + update(); } @@ -511,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 @@ -528,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; @@ -580,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 ); @@ -737,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 ) { @@ -869,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; @@ -890,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; @@ -915,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 @@ -964,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[ @@ -1029,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 - @@ -1113,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 ); @@ -1285,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, @@ -1311,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 ); @@ -1449,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 ) { @@ -1481,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 ); @@ -1510,8 +1513,11 @@ void AutomationEditor::paintEvent(QPaintEvent * pe ) case SELECT: cursor = s_toolSelect; break; case MOVE: cursor = s_toolMove; break; } - p.drawPixmap( mapFromGlobal( QCursor::pos() ) + QPoint( 8, 8 ), - *cursor ); + QPoint mousePosition = mapFromGlobal( QCursor::pos() ); + if( cursor != NULL && mousePosition.y() > TOP_MARGIN + SCROLLBAR_SIZE) + { + p.drawPixmap( mousePosition + QPoint( 8, 8 ), *cursor ); + } } @@ -1520,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() ); } @@ -1681,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); @@ -1952,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(); @@ -2089,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; } @@ -2110,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(); } @@ -2153,9 +2159,9 @@ void AutomationEditor::setQuantization() } else { - quantization = DefaultTicksPerTact; + quantization = DefaultTicksPerBar; } - quantization = DefaultTicksPerTact / quantization; + quantization = DefaultTicksPerBar / quantization; AutomationPattern::setQuantization( quantization ); update(); @@ -2294,26 +2300,11 @@ AutomationEditorWindow::AutomationEditorWindow() : /*DropToolBar *copyPasteActionsToolBar = addDropToolBarToTop(tr("Copy paste actions"));*/ QAction* cutAction = new QAction(embed::getIconPixmap("edit_cut"), - tr("Cut selected values (%1+X)").arg( - #ifdef LMMS_BUILD_APPLE - "⌘"), this); - #else - "Ctrl"), this); - #endif + tr("Cut selected values (%1+X)").arg(UI_CTRL_KEY), this); QAction* copyAction = new QAction(embed::getIconPixmap("edit_copy"), - tr("Copy selected values (%1+C)").arg( - #ifdef LMMS_BUILD_APPLE - "⌘"), this); - #else - "Ctrl"), this); - #endif + tr("Copy selected values (%1+C)").arg(UI_CTRL_KEY), this); QAction* pasteAction = new QAction(embed::getIconPixmap("edit_paste"), - tr("Paste values from clipboard (%1+V)").arg( - #ifdef LMMS_BUILD_APPLE - "⌘"), this); - #else - "Ctrl"), this); - #endif + tr("Paste values from clipboard (%1+V)").arg(UI_CTRL_KEY), this); cutAction->setShortcut(Qt::CTRL | Qt::Key_X); copyAction->setShortcut(Qt::CTRL | Qt::Key_C); @@ -2502,6 +2493,9 @@ void AutomationEditorWindow::dropEvent( QDropEvent *_de ) void AutomationEditorWindow::dragEnterEvent( QDragEnterEvent *_dee ) { + if (! m_editor->validPattern() ) { + return; + } StringPairDrag::processDragEnterEvent( _dee, "automatable_model" ); } @@ -2524,6 +2518,11 @@ void AutomationEditorWindow::clearCurrentPattern() setCurrentPattern(nullptr); } +void AutomationEditorWindow::focusInEvent(QFocusEvent * event) +{ + m_editor->setFocus( event->reason() ); +} + void AutomationEditorWindow::play() { m_editor->play(); diff --git a/src/gui/editors/BBEditor.cpp b/src/gui/editors/BBEditor.cpp index dde3cf95c..56fe29856 100644 --- a/src/gui/editors/BBEditor.cpp +++ b/src/gui/editors/BBEditor.cpp @@ -250,7 +250,25 @@ void BBTrackContainerView::dropEvent(QDropEvent* de) DataFile dataFile( value.toUtf8() ); Track * t = Track::create( dataFile.content().firstChild().toElement(), model() ); - t->deleteTCOs(); + // Ensure BB TCOs exist + bool hasValidBBTCOs = false; + if (t->getTCOs().size() == m_bbtc->numOfBBs()) + { + hasValidBBTCOs = true; + for (int i = 0; i < t->getTCOs().size(); ++i) + { + if (t->getTCOs()[i]->startPosition() != MidiTime(i, 0)) + { + hasValidBBTCOs = false; + break; + } + } + } + if (!hasValidBBTCOs) + { + t->deleteTCOs(); + t->createTCOsForBB(m_bbtc->numOfBBs() - 1); + } m_bbtc->updateAfterTrackAdd(); de->accept(); diff --git a/src/gui/editors/Editor.cpp b/src/gui/editors/Editor.cpp index bdc3e55d4..c27eda4c0 100644 --- a/src/gui/editors/Editor.cpp +++ b/src/gui/editors/Editor.cpp @@ -32,6 +32,7 @@ #include #include #include +#include void Editor::setPauseIcon(bool displayPauseIcon) @@ -73,11 +74,12 @@ void Editor::togglePlayStop() play(); } -Editor::Editor(bool record) : +Editor::Editor(bool record, bool stepRecord) : m_toolBar(new DropToolBar(this)), m_playAction(nullptr), m_recordAction(nullptr), m_recordAccompanyAction(nullptr), + m_toggleStepRecordingAction(nullptr), m_stopAction(nullptr) { m_toolBar = addDropToolBarToTop(tr("Transport controls")); @@ -93,11 +95,13 @@ Editor::Editor(bool record) : m_recordAction = new QAction(embed::getIconPixmap("record"), tr("Record"), this); m_recordAccompanyAction = new QAction(embed::getIconPixmap("record_accompany"), tr("Record while playing"), this); + m_toggleStepRecordingAction = new QAction(embed::getIconPixmap("record_step_off"), tr("Toggle Step Recording"), this); // Set up connections connect(m_playAction, SIGNAL(triggered()), this, SLOT(play())); connect(m_recordAction, SIGNAL(triggered()), this, SLOT(record())); connect(m_recordAccompanyAction, SIGNAL(triggered()), this, SLOT(recordAccompany())); + connect(m_toggleStepRecordingAction, SIGNAL(triggered()), this, SLOT(toggleStepRecording())); connect(m_stopAction, SIGNAL(triggered()), this, SLOT(stop())); new QShortcut(Qt::Key_Space, this, SLOT(togglePlayStop())); @@ -108,6 +112,10 @@ Editor::Editor(bool record) : addButton(m_recordAction, "recordButton"); addButton(m_recordAccompanyAction, "recordAccompanyButton"); } + if(stepRecord) + { + addButton(m_toggleStepRecordingAction, "stepRecordButton"); + } addButton(m_stopAction, "stopButton"); } @@ -121,8 +129,18 @@ QAction *Editor::playAction() const return m_playAction; } - - +void Editor::closeEvent( QCloseEvent * _ce ) +{ + if( parentWidget() ) + { + parentWidget()->hide(); + } + else + { + hide(); + } + _ce->ignore(); + } DropToolBar::DropToolBar(QWidget* parent) : QToolBar(parent) { @@ -138,3 +156,6 @@ void DropToolBar::dropEvent(QDropEvent* event) { dropped(event); } + + + diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index 1060574c9..3b42bd9b2 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -24,6 +24,8 @@ * */ +#include "PianoRoll.h" + #include #include #include @@ -34,7 +36,6 @@ #include #include #include -#include #ifndef __USE_XOPEN #define __USE_XOPEN @@ -46,7 +47,6 @@ #include "AutomationEditor.h" #include "ActionGroup.h" #include "ConfigManager.h" -#include "PianoRoll.h" #include "BBTrackContainer.h" #include "Clipboard.h" #include "ComboBox.h" @@ -62,12 +62,9 @@ #include "stdshims.h" #include "TextFloat.h" #include "TimeLineWidget.h" +#include "StepRecorderWidget.h" -#if QT_VERSION < 0x040800 -#define MiddleButton MidButton -#endif - using std::move; typedef AutomationPattern::timeMap timeMap; @@ -142,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 }; @@ -171,20 +168,25 @@ 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 ), m_lastKey( 0 ), m_editMode( ModeDraw ), + m_ctrlMode( ModeDraw ), m_mouseDownRight( false ), m_scrollBack( false ), + 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 ), m_lineColor( 0, 0, 0 ), m_noteModeColor( 0, 0, 0 ), m_noteColor( 0, 0, 0 ), + m_ghostNoteColor( 0, 0, 0 ), + m_ghostNoteTextColor( 0, 0, 0 ), m_barColor( 0, 0, 0 ), m_selectedNoteColor( 0, 0, 0 ), m_textColor( 0, 0, 0 ), @@ -192,27 +194,24 @@ PianoRoll::PianoRoll() : m_textShadow( 0, 0, 0 ), m_markedSemitoneColor( 0, 0, 0 ), m_noteOpacity( 255 ), + m_ghostNoteOpacity( 255 ), m_noteBorders( true ), + m_ghostNoteBorders( true ), m_backgroundShade( 0, 0, 0 ) { // gui names of edit modes 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 ); @@ -222,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 ); @@ -242,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 ); @@ -312,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, @@ -322,6 +312,10 @@ PianoRoll::PianoRoll() : connect( m_timeLine, SIGNAL( positionChanged( const MidiTime & ) ), this, SLOT( updatePosition( const MidiTime & ) ) ); + //update timeline when in step-recording mode + connect( &m_stepRecorderWidget, SIGNAL( positionChanged( const MidiTime & ) ), + this, SLOT( updatePositionStepRecording( const MidiTime & ) ) ); + // update timeline when in record-accompany mode connect( Engine::getSong()->getPlayPos( Song::Mode_PlaySong ).m_timeLine, SIGNAL( positionChanged( const MidiTime & ) ), @@ -394,7 +388,7 @@ PianoRoll::PianoRoll() : // Note length change can cause a redraw if Q is set to lock connect( &m_noteLenModel, SIGNAL( dataChanged() ), - this, SLOT( quantizeChanged() ) ); + this, SLOT( noteLengthChanged() ) ); // Set up scale model const InstrumentFunctionNoteStacking::ChordTable& chord_table = @@ -443,6 +437,8 @@ PianoRoll::PianoRoll() : //connection for selecion from timeline connect( m_timeLine, SIGNAL( regionSelectedFromPixels( int, int ) ), this, SLOT( selectRegionFromPixels( int, int ) ) ); + + m_stepRecorder.initialize(); } @@ -451,6 +447,7 @@ void PianoRoll::reset() { m_lastNoteVolume = DefaultVolume; m_lastNotePanning = DefaultPanning; + clearGhostPattern(); } void PianoRoll::showTextFloat(const QString &text, const QPoint &pos, int timeout) @@ -516,7 +513,7 @@ void PianoRoll::markSemiTone( int i ) break; case stmaMarkCurrentSemiTone: { - QList::iterator it = qFind( m_markedSemiTones.begin(), m_markedSemiTones.end(), key ); + QList::iterator it = std::find( m_markedSemiTones.begin(), m_markedSemiTones.end(), key ); if( it != m_markedSemiTones.end() ) { m_markedSemiTones.erase( it ); @@ -537,8 +534,11 @@ void PianoRoll::markSemiTone( int i ) QList::iterator i; for (int ix = 0; ix < aok.size(); ++ix) { - i = qFind(m_markedSemiTones.begin(), m_markedSemiTones.end(), aok.at(ix)); - m_markedSemiTones.erase(i); + i = std::find(m_markedSemiTones.begin(), m_markedSemiTones.end(), aok.at(ix)); + if (i != m_markedSemiTones.end()) + { + m_markedSemiTones.erase(i); + } } } else @@ -591,7 +591,7 @@ void PianoRoll::markSemiTone( int i ) ; } - qSort( m_markedSemiTones.begin(), m_markedSemiTones.end(), qGreater() ); + 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() ); } @@ -602,6 +602,74 @@ PianoRoll::~PianoRoll() } +void PianoRoll::setGhostPattern( Pattern* newPattern ) +{ + // Expects a pointer to a pattern or nullptr. + m_ghostNotes.clear(); + if( newPattern != nullptr ) + { + for( Note *note : newPattern->notes() ) + { + Note * new_note = new Note( note->length(), note->pos(), note->key() ); + m_ghostNotes.push_back( new_note ); + } + emit ghostPatternSet( true ); + } +} + + +void PianoRoll::loadGhostNotes( const QDomElement & de ) +{ + // Load ghost notes from DOM element. + if( de.isElement() ) + { + QDomNode node = de.firstChild(); + while( !node.isNull() ) + { + Note * n = new Note; + n->restoreState( node.toElement() ); + m_ghostNotes.push_back( n ); + node = node.nextSibling(); + } + emit ghostPatternSet( true ); + } +} + + +void PianoRoll::clearGhostPattern() +{ + setGhostPattern( nullptr ); + emit ghostPatternSet( false ); + update(); +} + + +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() ) @@ -616,12 +684,19 @@ void PianoRoll::setCurrentPattern( Pattern* newPattern ) Engine::getSong()->playPattern( NULL ); } + if(m_stepRecorder.isRecording()) + { + m_stepRecorder.stop(); + } + // set new data m_pattern = newPattern; m_currentPosition = 0; m_currentNote = NULL; m_startKey = INITIAL_START_KEY; + m_stepRecorder.setCurrentPattern(newPattern); + if( ! hasValidPattern() ) { //resizeEvent( NULL ); @@ -649,7 +724,7 @@ void PianoRoll::setCurrentPattern( Pattern* newPattern ) { central_key = central_key / total_notes - ( KeysPerOctave * NumOctaves - m_totalKeysToScroll ) / 2; - m_startKey = tLimit( central_key, 0, NumOctaves * KeysPerOctave ); + m_startKey = qBound( 0, central_key, NumOctaves * KeysPerOctave ); } // resizeEvent() does the rest for us (scrolling, range-checking @@ -684,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; } @@ -750,6 +825,12 @@ QColor PianoRoll::noteColor() const void PianoRoll::setNoteColor( const QColor & c ) { m_noteColor = c; } +QColor PianoRoll::noteTextColor() const +{ return m_noteTextColor; } + +void PianoRoll::setNoteTextColor( const QColor & c ) +{ m_noteTextColor = c; } + QColor PianoRoll::barColor() const { return m_barColor; } @@ -798,6 +879,30 @@ bool PianoRoll::noteBorders() const void PianoRoll::setNoteBorders( const bool b ) { m_noteBorders = b; } +QColor PianoRoll::ghostNoteColor() const +{ return m_ghostNoteColor; } + +void PianoRoll::setGhostNoteColor( const QColor & c ) +{ m_ghostNoteColor = c; } + +QColor PianoRoll::ghostNoteTextColor() const +{ return m_ghostNoteTextColor; } + +void PianoRoll::setGhostNoteTextColor( const QColor & c ) +{ m_ghostNoteTextColor = c; } + +int PianoRoll::ghostNoteOpacity() const +{ return m_ghostNoteOpacity; } + +void PianoRoll::setGhostNoteOpacity( const int i ) +{ m_ghostNoteOpacity = i; } + +bool PianoRoll::ghostNoteBorders() const +{ return m_ghostNoteBorders; } + +void PianoRoll::setGhostNoteBorders( const bool b ) +{ m_ghostNoteBorders = b; } + QColor PianoRoll::backgroundShade() const { return m_backgroundShade; } @@ -807,10 +912,9 @@ void PianoRoll::setBackgroundShade( const QColor & c ) - void PianoRoll::drawNoteRect( QPainter & p, int x, int y, - int width, const Note * n, const QColor & noteCol, - const QColor & selCol, const int noteOpc, const bool borders ) + int width, const Note * n, const QColor & noteCol, const QColor & noteTextColor, + const QColor & selCol, const int noteOpc, const bool borders, bool drawNoteName ) { ++x; ++y; @@ -821,15 +925,19 @@ void PianoRoll::drawNoteRect( QPainter & p, int x, int y, width = 2; } - int volVal = qMin( 255, 100 + (int) ( ( (float)( n->getVolume() - MinVolume ) ) / - ( (float)( MaxVolume - MinVolume ) ) * 155.0f) ); - float rightPercent = qMin( 1.0f, - ( (float)( n->getPanning() - PanningLeft ) ) / - ( (float)( PanningRight - PanningLeft ) ) * 2.0f ); + // Volume + float const volumeRange = static_cast(MaxVolume - MinVolume); + float const volumeSpan = static_cast(n->getVolume() - MinVolume); + float const volumeRatio = volumeSpan / volumeRange; + int volVal = qMin( 255, 100 + static_cast( volumeRatio * 155.0f) ); - float leftPercent = qMin( 1.0f, - ( (float)( PanningRight - n->getPanning() ) ) / - ( (float)( PanningRight - PanningLeft ) ) * 2.0f ); + // Panning + float const panningRange = static_cast(PanningRight - PanningLeft); + float const leftPanSpan = static_cast(PanningRight - n->getPanning()); + float const rightPanSpan = static_cast(n->getPanning() - PanningLeft); + + float leftPercent = qMin( 1.0f, leftPanSpan / panningRange * 2.0f ); + float rightPercent = qMin( 1.0f, rightPanSpan / panningRange * 2.0f ); QColor col = QColor( noteCol ); QPen pen; @@ -847,9 +955,9 @@ void PianoRoll::drawNoteRect( QPainter & p, int x, int y, // adjust note to make it a bit faded if it has a lower volume // in stereo using gradients QColor lcol = QColor::fromHsv( col.hue(), col.saturation(), - volVal * leftPercent, noteOpc ); + static_cast(volVal * leftPercent), noteOpc ); QColor rcol = QColor::fromHsv( col.hue(), col.saturation(), - volVal * rightPercent, noteOpc ); + static_cast(volVal * rightPercent), noteOpc ); QLinearGradient gradient( x, y, x, y + noteHeight ); gradient.setColorAt( 0, rcol ); @@ -867,6 +975,36 @@ void PianoRoll::drawNoteRect( QPainter & p, int x, int y, p.drawRect( x, y, noteWidth, noteHeight ); + // Draw note key text + if (drawNoteName) + { + p.save(); + int const noteTextHeight = static_cast(noteHeight * 0.8); + if (noteTextHeight > 6) + { + QString noteKeyString = getNoteString(n->key()); + + QFont noteFont(p.font()); + noteFont.setPixelSize(noteTextHeight); + QFontMetrics fontMetrics(noteFont); + QSize textSize = fontMetrics.size(Qt::TextSingleLine, noteKeyString); + + int const distanceToBorder = 2; + int const xOffset = borderWidth + distanceToBorder; + int const yOffset = (noteHeight + noteTextHeight) / 2; + + if (textSize.width() < noteWidth - xOffset) + { + p.setPen(noteTextColor); + p.setFont(noteFont); + QPoint textStart(x + xOffset, y + yOffset); + + p.drawText(textStart, noteKeyString); + } + } + p.restore(); + } + // draw the note endmark, to hint the user to resize p.setBrush( col ); if( width > 2 ) @@ -884,6 +1022,9 @@ void PianoRoll::drawDetuningInfo( QPainter & _p, const Note * _n, int _x, { int middle_y = _y + KEY_LINE_HEIGHT / 2; _p.setPen( noteColor() ); + _p.setClipRect(WHITE_KEY_WIDTH, PR_TOP_MARGIN, + width() - WHITE_KEY_WIDTH, + keyAreaBottom() - PR_TOP_MARGIN); int old_x = 0; int old_y = 0; @@ -892,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(); @@ -951,6 +1092,9 @@ void PianoRoll::clearSelectedNotes() void PianoRoll::shiftSemiTone( int amount ) // shift notes by amount semitones { + if (!hasValidPattern()) {return;} + + m_pattern->addJournalCheckPoint(); bool useAllNotes = ! isSelection(); for( Note *note : m_pattern->notes() ) { @@ -975,6 +1119,9 @@ void PianoRoll::shiftSemiTone( int amount ) // shift notes by amount semitones void PianoRoll::shiftPos( int amount ) //shift notes pos by amount { + if (!hasValidPattern()) {return;} + + m_pattern->addJournalCheckPoint(); bool useAllNotes = ! isSelection(); bool first = true; @@ -1042,15 +1189,28 @@ int PianoRoll::selectionCount() const // how many notes are selected? -void PianoRoll::keyPressEvent(QKeyEvent* ke ) +void PianoRoll::keyPressEvent(QKeyEvent* ke) { + if(m_stepRecorder.isRecording()) + { + bool handled = m_stepRecorder.keyPressEvent(ke); + if(handled) + { + ke->accept(); + update(); + return; + } + } + if( hasValidPattern() && ke->modifiers() == Qt::NoModifier ) { const int key_num = PianoView::getKeyFromKeyEvent( ke ) + ( DefaultOctave - 1 ) * KeysPerOctave; - if(! ke->isAutoRepeat() && key_num > -1) + if (!ke->isAutoRepeat() && key_num > -1) { - m_pattern->instrumentTrack()->pianoModel()->handleKeyPress( key_num ); + m_pattern->instrumentTrack()->pianoModel()->handleKeyPress(key_num); + // if a chord is set, play all chord notes (simulate click on all): + playChordNotes(key_num); ke->accept(); } } @@ -1065,12 +1225,18 @@ void PianoRoll::keyPressEvent(QKeyEvent* ke ) { // shift selection up an octave // if nothing selected, shift _everything_ - shiftSemiTone( 12 * direction ); + if (hasValidPattern()) + { + shiftSemiTone( 12 * direction ); + } } else if((ke->modifiers() & Qt::ShiftModifier) && m_action == ActionNone) { // Move selected notes up by one semitone - shiftSemiTone( 1 * direction ); + if (hasValidPattern()) + { + shiftSemiTone( 1 * direction ); + } } else { @@ -1100,22 +1266,32 @@ void PianoRoll::keyPressEvent(QKeyEvent* ke ) if( ke->modifiers() & Qt::ControlModifier && m_action == ActionNone ) { // Move selected notes by one bar to the left - shiftPos( direction * MidiTime::ticksPerTact() ); + if (hasValidPattern()) + { + shiftPos( direction * MidiTime::ticksPerBar() ); + } } else if( ke->modifiers() & Qt::ShiftModifier && m_action == ActionNone) { // move notes - bool quantized = ! ( ke->modifiers() & Qt::AltModifier ); - int amt = quantized ? quantization() : 1; - shiftPos( direction * amt ); + if (hasValidPattern()) + { + bool quantized = ! ( ke->modifiers() & Qt::AltModifier ); + int amt = quantized ? quantization() : 1; + shiftPos( direction * amt ); + } } else if( ke->modifiers() & Qt::AltModifier) { // switch to editing a pattern adjacent to this one in the song editor - Pattern * p = direction > 0 ? m_pattern->nextPattern() : m_pattern->previousPattern(); - if(p != NULL) + if (hasValidPattern()) { - setCurrentPattern(p); + Pattern * p = direction > 0 ? m_pattern->nextPattern() + : m_pattern->previousPattern(); + if(p != NULL) + { + setCurrentPattern(p); + } } } else @@ -1163,6 +1339,7 @@ void PianoRoll::keyPressEvent(QKeyEvent* ke ) clearSelectedNotes(); break; + case Qt::Key_Backspace: case Qt::Key_Delete: deleteSelectedNotes(); ke->accept(); @@ -1231,10 +1408,11 @@ void PianoRoll::keyReleaseEvent(QKeyEvent* ke ) if( hasValidPattern() && ke->modifiers() == Qt::NoModifier ) { const int key_num = PianoView::getKeyFromKeyEvent( ke ) + ( DefaultOctave - 1 ) * KeysPerOctave; - - if( ! ke->isAutoRepeat() && key_num > -1 ) + if (!ke->isAutoRepeat() && key_num > -1) { - m_pattern->instrumentTrack()->pianoModel()->handleKeyRelease( key_num ); + m_pattern->instrumentTrack()->pianoModel()->handleKeyRelease(key_num); + // if a chord is set, simulate click release on all chord notes + pauseChordNotes(key_num); ke->accept(); } } @@ -1272,6 +1450,7 @@ void PianoRoll::leaveEvent(QEvent * e ) QWidget::leaveEvent( e ); s_textFloat->hide(); + update(); // cleaning inner mouse-related graphics } @@ -1393,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; @@ -1423,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 ) ) ) { @@ -1567,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(); @@ -1679,7 +1858,9 @@ void PianoRoll::mousePressEvent(QMouseEvent * me ) { // left click - play the note int v = ( (float) x ) / ( (float) WHITE_KEY_WIDTH ) * MidiDefaultVelocity; - m_pattern->instrumentTrack()->pianoModel()->handleKeyPress( key_num, v ); + m_pattern->instrumentTrack()->pianoModel()->handleKeyPress(key_num, v); + // if a chord is set, play the chords notes as well: + playChordNotes(key_num, v); } } else @@ -1721,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; @@ -1767,6 +1948,10 @@ void PianoRoll::mouseDoubleClickEvent(QMouseEvent * me ) enterValue( &nv ); } } + else + { + QWidget::mouseDoubleClickEvent(me); + } } @@ -1776,13 +1961,16 @@ void PianoRoll::testPlayNote( Note * n ) { m_lastKey = n->key(); - if( ! n->isPlaying() && ! m_recording ) + if( ! n->isPlaying() && ! m_recording && ! m_stepRecorder.isRecording()) { n->setIsPlaying( true ); const int baseVelocity = m_pattern->instrumentTrack()->midiPort()->baseVelocity(); - m_pattern->instrumentTrack()->pianoModel()->handleKeyPress( n->key(), n->midiVelocity( baseVelocity ) ); + m_pattern->instrumentTrack()->pianoModel()->handleKeyPress(n->key(), n->midiVelocity(baseVelocity)); + + // if a chord is set, play the chords notes as well: + playChordNotes(n->key(), n->midiVelocity(baseVelocity)); MidiEvent event( MidiMetaEvent, -1, n->key(), panningToMidi( n->getPanning() ) ); @@ -1805,6 +1993,9 @@ void PianoRoll::pauseTestNotes( bool pause ) { // stop note m_pattern->instrumentTrack()->pianoModel()->handleKeyRelease( note->key() ); + + // if a chord was set, stop the chords notes as well: + pauseChordNotes(note->key()); } else { @@ -1816,19 +2007,56 @@ void PianoRoll::pauseTestNotes( bool pause ) } } +void PianoRoll::playChordNotes(int key, int velocity) +{ + // if a chord is set, play the chords notes beside the base note. + Piano *pianoModel = m_pattern->instrumentTrack()->pianoModel(); + const InstrumentFunctionNoteStacking::Chord & chord = + InstrumentFunctionNoteStacking::ChordTable::getInstance().getChordByName( + m_chordModel.currentText()); + if (!chord.isEmpty()) + { + for (int i = 1; i < chord.size(); ++i) + { + pianoModel->handleKeyPress(key + chord[i], velocity); + } + } +} + +void PianoRoll::pauseChordNotes(int key) +{ + // if a chord was set, stop the chords notes beside the base note. + Piano *pianoModel = m_pattern->instrumentTrack()->pianoModel(); + const InstrumentFunctionNoteStacking::Chord & chord = + InstrumentFunctionNoteStacking::ChordTable::getInstance().getChordByName( + m_chordModel.currentText()); + if (!chord.isEmpty()) + { + for (int i = 1; i < chord.size(); ++i) + { + pianoModel->handleKeyRelease(key + chord[i]); + } + } +} + void PianoRoll::testPlayKey( int key, int velocity, int pan ) { + Piano *pianoModel = m_pattern->instrumentTrack()->pianoModel(); // turn off old key - m_pattern->instrumentTrack()->pianoModel()->handleKeyRelease( m_lastKey ); + pianoModel->handleKeyRelease( m_lastKey ); + // if a chord was set, stop the chords notes as well + pauseChordNotes(m_lastKey); // remember which one we're playing m_lastKey = key; // play new key - m_pattern->instrumentTrack()->pianoModel()->handleKeyPress( key, velocity ); + pianoModel->handleKeyPress( key, velocity ); + // and if a chord is set, play chord notes: + playChordNotes(key, velocity); } @@ -1958,6 +2186,7 @@ void PianoRoll::mouseReleaseEvent( QMouseEvent * me ) { m_pattern->instrumentTrack()->pianoModel()-> handleKeyRelease( note->key() ); + pauseChordNotes(note->key()); note->setIsPlaying( false ); } } @@ -1965,6 +2194,7 @@ void PianoRoll::mouseReleaseEvent( QMouseEvent * me ) // stop playing keys that we let go of m_pattern->instrumentTrack()->pianoModel()-> handleKeyRelease( m_lastKey ); + pauseChordNotes(m_lastKey); } m_currentNote = NULL; @@ -2004,11 +2234,13 @@ void PianoRoll::mouseMoveEvent( QMouseEvent * me ) else if( m_action == ActionResizeNoteEditArea ) { // change m_notesEditHeight and then repaint - m_notesEditHeight = tLimit( - m_oldNotesEditHeight - ( me->y() - m_moveStartY ), + m_notesEditHeight = qBound( NOTE_EDIT_MIN_HEIGHT, + m_oldNotesEditHeight - ( me->y() - m_moveStartY ), height() - PR_TOP_MARGIN - NOTE_EDIT_RESIZE_BAR - PR_BOTTOM_MARGIN - KEY_AREA_MIN_HEIGHT ); + + m_stepRecorderWidget.setBottomMargin(PR_BOTTOM_MARGIN + m_notesEditHeight); repaint(); return; } @@ -2072,9 +2304,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(); @@ -2086,16 +2318,18 @@ void PianoRoll::mouseMoveEvent( QMouseEvent * me ) if( me->buttons() & Qt::LeftButton ) { - vol = tLimit( MinVolume + + vol = qBound( MinVolume, + MinVolume + ( ( (float)noteEditBottom() ) - ( (float)me->y() ) ) / ( (float)( noteEditBottom() - noteEditTop() ) ) * ( MaxVolume - MinVolume ), - MinVolume, MaxVolume ); - pan = tLimit( PanningLeft + + MaxVolume ); + pan = qBound( PanningLeft, + PanningLeft + ( (float)( noteEditBottom() - me->y() ) ) / ( (float)( noteEditBottom() - noteEditTop() ) ) * ( (float)( PanningRight - PanningLeft ) ), - PanningLeft, PanningRight); + PanningRight); } if( m_noteEditMode == NoteEditVolume ) @@ -2150,6 +2384,7 @@ void PianoRoll::mouseMoveEvent( QMouseEvent * me ) { // mouse not over this note, stop playing it. m_pattern->instrumentTrack()->pianoModel()->handleKeyRelease( n->key() ); + pauseChordNotes(n->key()); n->setIsPlaying( false ); } @@ -2167,8 +2402,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(); @@ -2200,7 +2435,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; @@ -2239,7 +2474,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; @@ -2261,7 +2496,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; @@ -2292,8 +2527,8 @@ void PianoRoll::mouseMoveEvent( QMouseEvent * me ) ( edit_note && pos_ticks <= note->pos() + NOTE_EDIT_LINE_WIDTH * - MidiTime::ticksPerTact() / - m_ppt ) + MidiTime::ticksPerBar() / + m_ppb ) ) ) { @@ -2342,7 +2577,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 - @@ -2403,7 +2638,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 @@ -2587,10 +2822,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 ) @@ -2887,20 +3122,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, @@ -2912,9 +3147,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 ); @@ -2967,6 +3202,50 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) QPolygonF editHandles; + // -- Begin ghost pattern + if( !m_ghostNotes.empty() ) + { + for( const Note *note : m_ghostNotes ) + { + int len_ticks = note->length(); + + if( len_ticks == 0 ) + { + continue; + } + else if( len_ticks < 0 ) + { + len_ticks = 4; + } + const int key = note->key() - m_startKey + 1; + + int pos_ticks = note->pos(); + + int note_width = len_ticks * m_ppb / MidiTime::ticksPerBar(); + const int x = ( pos_ticks - m_currentPosition ) * + m_ppb / MidiTime::ticksPerBar(); + // skip this note if not in visible area at all + if( !( x + note_width >= 0 && x <= width() - WHITE_KEY_WIDTH ) ) + { + continue; + } + + // is the note in visible area? + if( key > 0 && key <= visible_keys ) + { + + // we've done and checked all, let's draw the + // note + drawNoteRect( p, x + WHITE_KEY_WIDTH, + y_base - key * KEY_LINE_HEIGHT, + note_width, note, ghostNoteColor(), ghostNoteTextColor(), selectedNoteColor(), + ghostNoteOpacity(), ghostNoteBorders(), drawNoteNames ); + } + + } + } + // -- End ghost pattern + for( const Note *note : m_pattern->notes() ) { int len_ticks = note->length(); @@ -2984,9 +3263,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 ) ) { @@ -3001,8 +3280,8 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) // note drawNoteRect( p, x + WHITE_KEY_WIDTH, y_base - key * KEY_LINE_HEIGHT, - note_width, note, noteColor(), selectedNoteColor(), - noteOpacity(), noteBorders() ); + note_width, note, noteColor(), noteTextColor(), selectedNoteColor(), + noteOpacity(), noteBorders(), drawNoteNames ); } // draw note editing stuff @@ -3052,6 +3331,44 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) drawDetuningInfo( p, note, x + WHITE_KEY_WIDTH, y_base - key * KEY_LINE_HEIGHT ); + p.setClipRect(WHITE_KEY_WIDTH, PR_TOP_MARGIN, + width() - WHITE_KEY_WIDTH, + height() - PR_TOP_MARGIN); + } + } + + //draw current step recording notes + for( const Note *note : m_stepRecorder.getCurStepNotes() ) + { + int len_ticks = note->length(); + + if( len_ticks == 0 ) + { + continue; + } + + const int key = note->key() - m_startKey + 1; + + int pos_ticks = note->pos(); + + int note_width = len_ticks * m_ppb / MidiTime::ticksPerBar(); + const int x = ( pos_ticks - m_currentPosition ) * + m_ppb / MidiTime::ticksPerBar(); + // skip this note if not in visible area at all + if( !( x + note_width >= 0 && x <= width() - WHITE_KEY_WIDTH ) ) + { + continue; + } + + // is the note in visible area? + if( key > 0 && key <= visible_keys ) + { + + // we've done and checked all, let's draw the note + drawNoteRect( p, x + WHITE_KEY_WIDTH, + y_base - key * KEY_LINE_HEIGHT, + note_width, note, m_stepRecorder.curStepNoteColor(), noteTextColor(), selectedNoteColor(), + noteOpacity(), noteBorders(), drawNoteNames ); } } @@ -3076,10 +3393,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() ); @@ -3138,10 +3455,10 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) case ModeSelect: cursor = s_toolSelect; break; case ModeEditDetuning: cursor = s_toolOpen; break; } - if( cursor != NULL ) + QPoint mousePosition = mapFromGlobal( QCursor::pos() ); + if( cursor != NULL && mousePosition.y() > keyAreaTop() && mousePosition.x() > noteEditLeft()) { - p.drawPixmap( mapFromGlobal( QCursor::pos() ) + QPoint( 8, 8 ), - *cursor ); + p.drawPixmap( mousePosition + QPoint( 8, 8 ), *cursor ); } } @@ -3190,13 +3507,14 @@ void PianoRoll::wheelEvent(QWheelEvent * we ) if( we->x() > noteEditLeft() && we->x() < noteEditRight() && we->y() > noteEditTop() && we->y() < noteEditBottom() ) { + if (!hasValidPattern()) {return;} // get values for going through notes 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; @@ -3211,12 +3529,12 @@ void PianoRoll::wheelEvent(QWheelEvent * we ) } if( nv.size() > 0 ) { - const int step = we->delta() > 0 ? 1.0 : -1.0; + const int step = we->delta() > 0 ? 1 : -1; if( m_noteEditMode == NoteEditVolume ) { for ( Note * n : nv ) { - volume_t vol = tLimit( n->getVolume() + step, MinVolume, MaxVolume ); + volume_t vol = qBound( MinVolume, n->getVolume() + step, MaxVolume ); n->setVolume( vol ); } bool allVolumesEqual = std::all_of( nv.begin(), nv.end(), @@ -3235,7 +3553,7 @@ void PianoRoll::wheelEvent(QWheelEvent * we ) { for ( Note * n : nv ) { - panning_t pan = tLimit( n->getPanning() + step, PanningLeft, PanningRight ); + panning_t pan = qBound( PanningLeft, n->getPanning() + step, PanningRight ); n->setPanning( pan ); } bool allPansEqual = std::all_of( nv.begin(), nv.end(), @@ -3297,11 +3615,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 @@ -3332,8 +3650,9 @@ void PianoRoll::focusOutEvent( QFocusEvent * ) m_pattern->instrumentTrack()->pianoModel()->midiEventProcessor()->processInEvent( MidiEvent( MidiNoteOff, -1, i, 0 ) ); m_pattern->instrumentTrack()->pianoModel()->setKeyState( i, false ); } - update(); } + m_editMode = m_ctrlMode; + update(); } @@ -3452,6 +3771,34 @@ void PianoRoll::recordAccompany() +bool PianoRoll::toggleStepRecording() +{ + if(m_stepRecorder.isRecording()) + { + m_stepRecorder.stop(); + } + else + { + if(hasValidPattern()) + { + if(Engine::getSong()->isPlaying()) + { + m_stepRecorder.start(0, newNoteLen()); + } + else + { + m_stepRecorder.start( + Engine::getSong()->getPlayPos( + Song::Mode_PlayPattern), newNoteLen()); + } + } + } + + return m_stepRecorder.isRecording();; +} + + + void PianoRoll::stop() { @@ -3465,22 +3812,29 @@ void PianoRoll::stop() void PianoRoll::startRecordNote(const Note & n ) { - if( m_recording && hasValidPattern() && + if(hasValidPattern()) + { + if( m_recording && Engine::getSong()->isPlaying() && (Engine::getSong()->playMode() == desiredPlayModeForAccompany() || - Engine::getSong()->playMode() == Song::Mode_PlayPattern )) - { - MidiTime sub; - if( Engine::getSong()->playMode() == Song::Mode_PlaySong ) + Engine::getSong()->playMode() == Song::Mode_PlayPattern )) { - sub = m_pattern->startPosition(); + MidiTime sub; + if( Engine::getSong()->playMode() == Song::Mode_PlaySong ) + { + sub = m_pattern->startPosition(); + } + Note n1( 1, Engine::getSong()->getPlayPos( + Engine::getSong()->playMode() ) - sub, + n.key(), n.getVolume(), n.getPanning() ); + if( n1.pos() >= 0 ) + { + m_recordingNotes << n1; + } } - Note n1( 1, Engine::getSong()->getPlayPos( - Engine::getSong()->playMode() ) - sub, - n.key(), n.getVolume(), n.getPanning() ); - if( n1.pos() >= 0 ) + else if (m_stepRecorder.isRecording()) { - m_recordingNotes << n1; + m_stepRecorder.notePressed(n); } } } @@ -3490,28 +3844,35 @@ void PianoRoll::startRecordNote(const Note & n ) void PianoRoll::finishRecordNote(const Note & n ) { - if( m_recording && hasValidPattern() && - Engine::getSong()->isPlaying() && - ( Engine::getSong()->playMode() == - desiredPlayModeForAccompany() || - Engine::getSong()->playMode() == - Song::Mode_PlayPattern ) ) + if(hasValidPattern()) { - for( QList::Iterator it = m_recordingNotes.begin(); - it != m_recordingNotes.end(); ++it ) + if( m_recording && + Engine::getSong()->isPlaying() && + ( Engine::getSong()->playMode() == + desiredPlayModeForAccompany() || + Engine::getSong()->playMode() == + Song::Mode_PlayPattern ) ) { - if( it->key() == n.key() ) + for( QList::Iterator it = m_recordingNotes.begin(); + it != m_recordingNotes.end(); ++it ) { - Note n1( n.length(), it->pos(), - it->key(), it->getVolume(), - it->getPanning() ); - n1.quantizeLength( quantization() ); - m_pattern->addNote( n1 ); - update(); - m_recordingNotes.erase( it ); - break; + if( it->key() == n.key() ) + { + Note n1( n.length(), it->pos(), + it->key(), it->getVolume(), + it->getPanning() ); + n1.quantizeLength( quantization() ); + m_pattern->addNote( n1 ); + update(); + m_recordingNotes.erase( it ); + break; + } } } + else if (m_stepRecorder.isRecording()) + { + m_stepRecorder.noteReleased(n); + } } } @@ -3521,6 +3882,7 @@ void PianoRoll::finishRecordNote(const Note & n ) void PianoRoll::horScrolled(int new_pos ) { m_currentPosition = new_pos; + m_stepRecorderWidget.setCurrentPosition(m_currentPosition); emit positionChanged( m_currentPosition ); update(); } @@ -3541,7 +3903,7 @@ void PianoRoll::verScrolled( int new_pos ) void PianoRoll::setEditMode(int mode) { - m_editMode = (EditModes) mode; + m_ctrlMode = m_editMode = (EditModes) mode; } @@ -3681,7 +4043,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 ); @@ -3722,6 +4084,8 @@ void PianoRoll::cutSelectedNotes() if( ! selected_notes.empty() ) { + m_pattern->addJournalCheckPoint(); + copyToClipboard( selected_notes ); Engine::getSong()->setModified(); @@ -3840,15 +4204,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; } @@ -3891,15 +4255,24 @@ void PianoRoll::updatePositionAccompany( const MidiTime & t ) } +void PianoRoll::updatePositionStepRecording( const MidiTime & t ) +{ + if( m_stepRecorder.isRecording() ) + { + autoScroll( 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->setPixelsPerBar( m_ppb ); + m_stepRecorderWidget.setPixelsPerBar( m_ppb ); - m_timeLine->setPixelsPerTact( m_ppt ); update(); } @@ -3911,7 +4284,11 @@ void PianoRoll::quantizeChanged() update(); } - +void PianoRoll::noteLengthChanged() +{ + m_stepRecorder.setStepsLength(newNoteLen()); + update(); +} int PianoRoll::quantization() const @@ -3924,12 +4301,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(); } @@ -3997,7 +4374,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(); } @@ -4025,7 +4402,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() ) @@ -4048,7 +4425,7 @@ Note * PianoRoll::noteUnderMouse() PianoRollWindow::PianoRollWindow() : - Editor(true), + Editor(true, true), m_editor(new PianoRoll()) { setCentralWidget( m_editor ); @@ -4056,6 +4433,7 @@ PianoRollWindow::PianoRollWindow() : m_playAction->setToolTip(tr( "Play/pause current pattern (Space)" ) ); m_recordAction->setToolTip(tr( "Record notes from MIDI-device/channel-piano" ) ); m_recordAccompanyAction->setToolTip( tr( "Record notes from MIDI-device/channel-piano while playing song or BB track" ) ); + m_toggleStepRecordingAction->setToolTip( tr( "Record notes from MIDI-device/channel-piano, one step at the time" ) ); m_stopAction->setToolTip( tr( "Stop playing of current pattern (Space)" ) ); DropToolBar *notesActionsToolBar = addDropToolBarToTop( tr( "Edit actions" ) ); @@ -4090,28 +4468,13 @@ PianoRollWindow::PianoRollWindow() : DropToolBar *copyPasteActionsToolBar = addDropToolBarToTop( tr( "Copy paste controls" ) ); QAction* cutAction = new QAction(embed::getIconPixmap( "edit_cut" ), - tr( "Cut (%1+X)" ).arg( - #ifdef LMMS_BUILD_APPLE - "⌘" ), this ); - #else - "Ctrl" ), this ); - #endif + tr( "Cut (%1+X)" ).arg(UI_CTRL_KEY), this ); QAction* copyAction = new QAction(embed::getIconPixmap( "edit_copy" ), - tr( "Copy (%1+C)" ).arg( - #ifdef LMMS_BUILD_APPLE - "⌘"), this); - #else - "Ctrl" ), this ); - #endif + tr( "Copy (%1+C)" ).arg(UI_CTRL_KEY), this ); QAction* pasteAction = new QAction(embed::getIconPixmap( "edit_paste" ), - tr( "Paste (%1+V)" ).arg( - #ifdef LMMS_BUILD_APPLE - "⌘" ), this ); - #else - "Ctrl" ), this ); - #endif + tr( "Paste (%1+V)" ).arg(UI_CTRL_KEY), this ); cutAction->setShortcut( Qt::CTRL | Qt::Key_X ); copyAction->setShortcut( Qt::CTRL | Qt::Key_C ); @@ -4177,8 +4540,15 @@ PianoRollWindow::PianoRollWindow() : m_chordComboBox = new ComboBox( m_toolBar ); m_chordComboBox->setModel( &m_editor->m_chordModel ); m_chordComboBox->setFixedSize( 105, 22 ); - m_chordComboBox->setToolTip( tr( "Chord") ); + m_chordComboBox->setToolTip( tr( "Chord" ) ); + // -- Clear ghost pattern button + m_clearGhostButton = new QPushButton( m_toolBar ); + m_clearGhostButton->setIcon( embed::getIconPixmap( "clear_ghost_note" ) ); + m_clearGhostButton->setToolTip( tr( "Clear ghost notes" ) ); + m_clearGhostButton->setEnabled( false ); + connect( m_clearGhostButton, SIGNAL( clicked() ), m_editor, SLOT( clearGhostPattern() ) ); + connect( m_editor, SIGNAL( ghostPatternSet( bool ) ), this, SLOT( ghostPatternSet( bool ) ) ); zoomAndNotesToolBar->addWidget( zoom_lbl ); zoomAndNotesToolBar->addWidget( m_zoomingComboBox ); @@ -4199,6 +4569,9 @@ PianoRollWindow::PianoRollWindow() : zoomAndNotesToolBar->addWidget( chord_lbl ); zoomAndNotesToolBar->addWidget( m_chordComboBox ); + zoomAndNotesToolBar->addSeparator(); + zoomAndNotesToolBar->addWidget( m_clearGhostButton ); + // setup our actual window setFocusPolicy( Qt::StrongFocus ); setFocus(); @@ -4207,7 +4580,7 @@ PianoRollWindow::PianoRollWindow() : // Connections connect( m_editor, SIGNAL( currentPatternChanged() ), this, SIGNAL( currentPatternChanged() ) ); - connect( m_editor, SIGNAL( currentPatternChanged() ), this, SLOT( patternRenamed() ) ); + connect( m_editor, SIGNAL( currentPatternChanged() ), this, SLOT( updateAfterPatternChange() ) ); } @@ -4221,6 +4594,14 @@ const Pattern* PianoRollWindow::currentPattern() const +void PianoRollWindow::setGhostPattern( Pattern* pattern ) +{ + m_editor->setGhostPattern( pattern ); +} + + + + void PianoRollWindow::setCurrentPattern( Pattern* pattern ) { m_editor->setCurrentPattern( pattern ); @@ -4228,8 +4609,8 @@ void PianoRollWindow::setCurrentPattern( Pattern* pattern ) if ( pattern ) { setWindowTitle( tr( "Piano-Roll - %1" ).arg( pattern->name() ) ); - connect( pattern->instrumentTrack(), SIGNAL( nameChanged() ), this, SLOT( patternRenamed()) ); - connect( pattern, SIGNAL( dataChanged() ), this, SLOT( patternRenamed() ) ); + connect( pattern->instrumentTrack(), SIGNAL( nameChanged() ), this, SLOT( updateAfterPatternChange()) ); + connect( pattern, SIGNAL( dataChanged() ), this, SLOT( updateAfterPatternChange() ) ); } else { @@ -4274,6 +4655,8 @@ void PianoRollWindow::stop() void PianoRollWindow::record() { + stopStepRecording(); //step recording mode is mutually exclusive with other record modes + m_editor->record(); } @@ -4282,11 +4665,25 @@ void PianoRollWindow::record() void PianoRollWindow::recordAccompany() { + stopStepRecording(); //step recording mode is mutually exclusive with other record modes + m_editor->recordAccompany(); } +void PianoRollWindow::toggleStepRecording() +{ + if(isRecording()) + { + // step recording mode is mutually exclusive with other record modes + // stop them before starting step recording + stop(); + } + m_editor->toggleStepRecording(); + + updateStepRecordingIcon(); +} void PianoRollWindow::stopRecording() { @@ -4306,6 +4703,33 @@ void PianoRollWindow::reset() void PianoRollWindow::saveSettings( QDomDocument & doc, QDomElement & de ) { + if( !m_editor->ghostNotes().empty() ) + { + QDomElement ghostNotesRoot = doc.createElement( "ghostnotes" ); + for( Note *note : m_editor->ghostNotes() ) + { + QDomElement ghostNoteNode = doc.createElement( "ghostnote" ); + ghostNoteNode.setAttribute( "len", note->length() ); + ghostNoteNode.setAttribute( "key", note->key() ); + ghostNoteNode.setAttribute( "pos", note->pos() ); + + ghostNotesRoot.appendChild(ghostNoteNode); + } + 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 ); } @@ -4314,6 +4738,9 @@ 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 ); } @@ -4327,6 +4754,11 @@ QSize PianoRollWindow::sizeHint() const +void PianoRollWindow::updateAfterPatternChange() +{ + patternRenamed(); + updateStepRecordingIcon(); //pattern change turn step recording OFF - update icon accordingly +} void PianoRollWindow::patternRenamed() { @@ -4343,8 +4775,37 @@ void PianoRollWindow::patternRenamed() +void PianoRollWindow::ghostPatternSet( bool state ) +{ + m_clearGhostButton->setEnabled( state ); +} + + + + void PianoRollWindow::focusInEvent( QFocusEvent * event ) { // when the window is given focus, also give focus to the actual piano roll m_editor->setFocus( event->reason() ); } + +void PianoRollWindow::stopStepRecording() +{ + if(m_editor->isStepRecording()) + { + m_editor->toggleStepRecording(); + updateStepRecordingIcon(); + } +} + +void PianoRollWindow::updateStepRecordingIcon() +{ + if(m_editor->isStepRecording()) + { + m_toggleStepRecordingAction->setIcon(embed::getIconPixmap("record_step_on")); + } + else + { + m_toggleStepRecordingAction->setIcon(embed::getIconPixmap("record_step_off")); + } +} diff --git a/src/gui/editors/SongEditor.cpp b/src/gui/editors/SongEditor.cpp index 64facd6b0..53f73228e 100644 --- a/src/gui/editors/SongEditor.cpp +++ b/src/gui/editors/SongEditor.cpp @@ -51,7 +51,7 @@ #include "TimeDisplayWidget.h" #include "AudioDevice.h" #include "PianoRoll.h" - +#include "Track.h" positionLine::positionLine( QWidget * parent ) : QWidget( parent ) @@ -77,18 +77,26 @@ SongEditor::SongEditor( Song * song ) : TrackContainerView( song ), m_song( song ), m_zoomingModel(new ComboBoxModel()), + m_snappingModel(new ComboBoxModel()), + m_proportionalSnap( false ), 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 - m_widgetWidthTotal = 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( m_widgetWidthTotal, 32, - pixelsPerTact(), + m_snappingModel->setParent(this); + m_timeLine = new TimeLineWidget( m_trackHeadWidth, 32, + pixelsPerBar(), m_song->m_playPos[Song::Mode_PlaySong], m_currentPosition, Song::Mode_PlaySong, this ); @@ -235,8 +243,12 @@ 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 + + //Set up zooming model for( float const & zoomLevel : m_zoomLevels ) { m_zoomingModel->addItem( QString( "%1\%" ).arg( zoomLevel * 100 ) ); @@ -246,6 +258,24 @@ SongEditor::SongEditor( Song * song ) : connect( m_zoomingModel, SIGNAL( dataChanged() ), this, SLOT( zoomingChanged() ) ); + //Set up snapping model, 2^i + for ( int i = 3; i >= -4; i-- ) + { + if ( i > 0 ) + { + m_snappingModel->addItem( QString( "%1 Bars").arg( 1 << i ) ); + } + else if ( i == 0 ) + { + m_snappingModel->addItem( "1 Bar" ); + } + else + { + m_snappingModel->addItem( QString( "1/%1 Bar" ).arg( 1 << (-i) ) ); + } + } + m_snappingModel->setInitValue( m_snappingModel->findText( "1 Bar" ) ); + setFocusPolicy( Qt::StrongFocus ); setFocus(); } @@ -270,6 +300,48 @@ void SongEditor::loadSettings( const QDomElement& element ) +float SongEditor::getSnapSize() const +{ + // 1 Bar is the third value in the snapping dropdown + int val = -m_snappingModel->value() + 3; + // If proportional snap is on, we snap to finer values when zoomed in + if (m_proportionalSnap) + { + val = val - m_zoomingModel->value() + 3; + } + val = max(val, -6); // -6 gives 1/64th bar snapping. Lower values cause crashing. + + if ( val >= 0 ){ + return 1 << val; + } + else { + return 1.0 / ( 1 << -val ); + } +} + +QString SongEditor::getSnapSizeString() const +{ + int val = -m_snappingModel->value() + 3; + val = val - m_zoomingModel->value() + 3; + val = max(val, -6); // -6 gives 1/64th bar snapping. Lower values cause crashing. + + if ( val >= 0 ){ + int bars = 1 << val; + if ( bars == 1 ) { return QString("1 Bar"); } + else + { + return QString( "%1 Bars" ).arg(bars); + } + } + else { + int div = ( 1 << -val ); + return QString( "1/%1 Bar" ).arg(div); + } +} + + + + void SongEditor::setHighQuality( bool hq ) { Engine::mixer()->changeQuality( Mixer::qualitySettings( @@ -289,6 +361,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) + / pixelsPerBar() * MidiTime::ticksPerBar()) + + 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()) * pixelsPerBar(); + 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) + / pixelsPerBar() * MidiTime::ticksPerBar()) + + 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; @@ -304,24 +469,29 @@ void SongEditor::setEditModeSelect() setEditMode(SelectMode); } +void SongEditor::toggleProportionalSnap() +{ + m_proportionalSnap = !m_proportionalSnap; +} + void SongEditor::keyPressEvent( QKeyEvent * ke ) { if( ke->modifiers() & Qt::ShiftModifier && - ke->key() == Qt::Key_Insert ) + ( ke->key() == Qt::Key_Insert || ke->key() == Qt::Key_Enter || ke->key() == Qt::Key_Return ) ) { m_song->insertBar(); } else if( ke->modifiers() & Qt::ShiftModifier && - ke->key() == Qt::Key_Delete ) + ( ke->key() == Qt::Key_Delete || ke->key() == Qt::Key_Backspace ) ) { m_song->removeBar(); } 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 ); @@ -329,7 +499,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 ); @@ -385,20 +555,20 @@ void SongEditor::wheelEvent( QWheelEvent * we ) z = qBound( 0, z, m_zoomingModel->size() - 1 ); - int x = (we->x() - m_widgetWidthTotal); - // 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(); } @@ -418,7 +588,7 @@ void SongEditor::wheelEvent( QWheelEvent * we ) void SongEditor::closeEvent( QCloseEvent * ce ) - { +{ if( parentWidget() ) { parentWidget()->hide(); @@ -428,7 +598,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) + / pixelsPerBar() * MidiTime::ticksPerBar()) + + 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); +} @@ -581,14 +797,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; } @@ -621,11 +837,12 @@ 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(); } @@ -651,6 +868,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; @@ -659,10 +896,19 @@ ComboBoxModel *SongEditor::zoomingModel() const +ComboBoxModel *SongEditor::snappingModel() const +{ + return m_snappingModel; +} + + + + SongEditorWindow::SongEditorWindow(Song* song) : - Editor(Engine::mixer()->audioDev()->supportsCapture()), + Editor(Engine::mixer()->audioDev()->supportsCapture(), false), m_editor(new SongEditor(song)), - m_crtlAction( NULL ) + m_crtlAction( NULL ), + m_snapSizeLabel( new QLabel( m_toolBar ) ) { setWindowTitle( tr( "Song-Editor" ) ); setWindowIcon( embed::getIconPixmap( "songeditor" ) ); @@ -724,23 +970,63 @@ SongEditorWindow::SongEditorWindow(Song* song) : QLabel * zoom_lbl = new QLabel( m_toolBar ); zoom_lbl->setPixmap( embed::getIconPixmap( "zoom" ) ); - // setup zooming-stuff + //Set up zooming-stuff m_zoomingComboBox = new ComboBox( m_toolBar ); m_zoomingComboBox->setFixedSize( 80, 22 ); m_zoomingComboBox->move( 580, 4 ); m_zoomingComboBox->setModel(m_editor->m_zoomingModel); m_zoomingComboBox->setToolTip(tr("Horizontal zooming")); + connect(m_editor->zoomingModel(), SIGNAL(dataChanged()), this, SLOT(updateSnapLabel())); zoomToolBar->addWidget( zoom_lbl ); zoomToolBar->addWidget( m_zoomingComboBox ); + DropToolBar *snapToolBar = addDropToolBarToTop(tr("Snap controls")); + QLabel * snap_lbl = new QLabel( m_toolBar ); + snap_lbl->setPixmap( embed::getIconPixmap( "quantize" ) ); + + //Set up quantization/snapping selector + m_snappingComboBox = new ComboBox( m_toolBar ); + m_snappingComboBox->setFixedSize( 80, 22 ); + m_snappingComboBox->setModel(m_editor->m_snappingModel); + m_snappingComboBox->setToolTip(tr("Clip snapping size")); + connect(m_editor->snappingModel(), SIGNAL(dataChanged()), this, SLOT(updateSnapLabel())); + + m_setProportionalSnapAction = new QAction(embed::getIconPixmap("proportional_snap"), + tr("Toggle proportional snap on/off"), this); + m_setProportionalSnapAction->setCheckable(true); + m_setProportionalSnapAction->setChecked(false); + connect(m_setProportionalSnapAction, SIGNAL(triggered()), m_editor, SLOT(toggleProportionalSnap())); + connect(m_setProportionalSnapAction, SIGNAL(triggered()), this, SLOT(updateSnapLabel()) ); + + snapToolBar->addWidget( snap_lbl ); + snapToolBar->addWidget( m_snappingComboBox ); + snapToolBar->addSeparator(); + snapToolBar->addAction( m_setProportionalSnapAction ); + + snapToolBar->addSeparator(); + snapToolBar->addWidget( m_snapSizeLabel ); + connect(song, SIGNAL(projectLoaded()), this, SLOT(adjustUiAfterProjectLoad())); connect(this, SIGNAL(resized()), m_editor, SLOT(updatePositionLine())); } QSize SongEditorWindow::sizeHint() const { - return {600, 300}; + return {720, 300}; +} + +void SongEditorWindow::updateSnapLabel(){ + if (m_setProportionalSnapAction->isChecked()) + { + m_snapSizeLabel->setText(QString("Snap: ") + m_editor->getSnapSizeString()); + m_snappingComboBox->setToolTip(tr("Base snapping size")); + } + else + { + m_snappingComboBox->setToolTip(tr("Clip snapping size")); + m_snapSizeLabel->clear(); + } } @@ -752,6 +1038,16 @@ void SongEditorWindow::resizeEvent(QResizeEvent *event) } +void SongEditorWindow::changeEvent(QEvent *event) +{ + QWidget::changeEvent(event); + if (event->type() == QEvent::WindowStateChange) + { + m_editor->realignTracks(); + } +} + + void SongEditorWindow::play() { emit playTriggered(); diff --git a/src/gui/embed.cpp b/src/gui/embed.cpp index af298bec3..6ce4b5bd7 100644 --- a/src/gui/embed.cpp +++ b/src/gui/embed.cpp @@ -31,8 +31,8 @@ namespace embed { - -QPixmap getIconPixmap(const QString& pixmapName, int width, int height ) +QPixmap getIconPixmap(const QString& pixmapName, + int width, int height, const char** xpm ) { QString cacheName; if (width > 0 && height > 0) @@ -50,19 +50,28 @@ QPixmap getIconPixmap(const QString& pixmapName, int width, int height ) { return pixmap; } - QImageReader reader(QString("artwork:%1").arg(pixmapName)); - if (width > 0 && height > 0) + if(xpm) { - reader.setScaledSize(QSize(width, height)); + pixmap = QPixmap(xpm); } - - pixmap = QPixmap::fromImageReader(&reader); - if (pixmap.isNull()) + else { - qWarning().nospace() << "Error loading icon pixmap " << pixmapName << ": " << - reader.errorString().toLocal8Bit().data(); - return QPixmap(1,1); + QImageReader reader(QString("artwork:%1").arg(pixmapName)); + + if (width > 0 && height > 0) + { + reader.setScaledSize(QSize(width, height)); + } + + pixmap = QPixmap::fromImageReader(&reader); + + if (pixmap.isNull()) + { + qWarning().nospace() << "Error loading icon pixmap " << pixmapName << ": " << + reader.errorString().toLocal8Bit().data(); + return QPixmap(1,1); + } } // Save to cache and return diff --git a/src/gui/menus/RecentProjectsMenu.cpp b/src/gui/menus/RecentProjectsMenu.cpp new file mode 100644 index 000000000..6f32b0df5 --- /dev/null +++ b/src/gui/menus/RecentProjectsMenu.cpp @@ -0,0 +1,78 @@ +#include "RecentProjectsMenu.h" + +#include + +#include "ConfigManager.h" +#include "Engine.h" +#include "Song.h" + +#include "embed.h" +#include "GuiApplication.h" +#include "MainWindow.h" + +RecentProjectsMenu::RecentProjectsMenu(QWidget *parent) : + QMenu(tr( "&Recently Opened Projects" ), parent) +{ + setIcon(embed::getIconPixmap( "project_open_recent" )); + + connect( this, SIGNAL( aboutToShow() ), + this, SLOT(fillMenu() ) ); + connect( this, SIGNAL( triggered( QAction * ) ), + this, SLOT(openProject(QAction * ) ) ); +} + + + + +void RecentProjectsMenu::fillMenu() +{ + clear(); + QStringList rup = ConfigManager::inst()->recentlyOpenedProjects(); + + auto projectFileIcon = embed::getIconPixmap( "project_file" ); + + // The file history goes 50 deep but we only show the 15 + // most recent ones that we can open and omit .mpt files. + int shownInMenu = 0; + for(QString& fileName : rup) + { + QFileInfo recentFile(fileName); + if (!recentFile.exists() || + fileName == ConfigManager::inst()->recoveryFile() ) + { + continue; + } + + if( recentFile.suffix().toLower() == "mpt" ) + { + continue; + } + + addAction(projectFileIcon, fileName.replace("&", "&&") ); +#ifdef LMMS_BUILD_APPLE + actions().last()->setIconVisibleInMenu(false); // QTBUG-44565 workaround + actions().last()->setIconVisibleInMenu(true); +#endif + + shownInMenu++; + if( shownInMenu >= 15 ) + { + break; + } + } +} + + + + +void RecentProjectsMenu::openProject(QAction * _action ) +{ + auto mainWindow = gui->mainWindow(); + if (mainWindow->mayChangeProject(true)) + { + const QString f = _action->text().replace("&&", "&"); + mainWindow->setCursor( Qt::WaitCursor ); + Engine::getSong()->loadProject( f ); + mainWindow->setCursor( Qt::ArrowCursor ); + } +} diff --git a/src/gui/menus/TemplatesMenu.cpp b/src/gui/menus/TemplatesMenu.cpp new file mode 100644 index 000000000..b944b7cf1 --- /dev/null +++ b/src/gui/menus/TemplatesMenu.cpp @@ -0,0 +1,69 @@ +#include "TemplatesMenu.h" + +#include "ConfigManager.h" +#include "Engine.h" +#include "Song.h" + +#include "embed.h" +#include "GuiApplication.h" +#include "MainWindow.h" + +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 * ) ) ); +} + + + + +void TemplatesMenu::createNewProjectFromTemplate(QAction * _action) +{ + if( gui->mainWindow()->mayChangeProject(true) ) + { + const QString& templateFilePath = _action->data().toString(); + Engine::getSong()->createNewProjectFromTemplate(templateFilePath); + } +} + + + + + +void TemplatesMenu::fillTemplatesMenu() +{ + clear(); + + addTemplatesFromDir(ConfigManager::inst()->userTemplateDir()); + addTemplatesFromDir(ConfigManager::inst()->factoryProjectsDir() + "templates"); +} + + + + +void TemplatesMenu::addTemplatesFromDir( const QDir& dir ) { + QFileInfoList templates = dir.entryInfoList( QStringList( "*.mpt" ), + QDir::Files | QDir::Readable ); + + if (!templates.empty() && !actions().isEmpty()) + { + addSeparator(); + } + + auto projectFileIcon = embed::getIconPixmap( "project_file" ); + + for(const QFileInfo& templateFile : templates) + { + auto action = addAction(projectFileIcon, + templateFile.completeBaseName().replace("&", "&&")); + action->setData(templateFile.absoluteFilePath()); +#ifdef LMMS_BUILD_APPLE + action->setIconVisibleInMenu(false); // QTBUG-44565 workaround + action->setIconVisibleInMenu(true); +#endif + } +} diff --git a/src/gui/widgets/AutomatableButton.cpp b/src/gui/widgets/AutomatableButton.cpp index d760ab06f..1d9cecce8 100644 --- a/src/gui/widgets/AutomatableButton.cpp +++ b/src/gui/widgets/AutomatableButton.cpp @@ -220,7 +220,7 @@ void automatableButtonGroup::addButton( AutomatableButton * _btn ) void automatableButtonGroup::removeButton( AutomatableButton * _btn ) { - m_buttons.erase( qFind( m_buttons.begin(), m_buttons.end(), _btn ) ); + m_buttons.erase( std::find( m_buttons.begin(), m_buttons.end(), _btn ) ); _btn->m_group = NULL; } diff --git a/src/gui/widgets/ComboBox.cpp b/src/gui/widgets/ComboBox.cpp index 99a06c5d5..c796bfa74 100644 --- a/src/gui/widgets/ComboBox.cpp +++ b/src/gui/widgets/ComboBox.cpp @@ -42,12 +42,12 @@ QPixmap * ComboBox::s_background = NULL; QPixmap * ComboBox::s_arrow = NULL; QPixmap * ComboBox::s_arrowSelected = NULL; -const int CB_ARROW_BTN_WIDTH = 20; +const int CB_ARROW_BTN_WIDTH = 18; ComboBox::ComboBox( QWidget * _parent, const QString & _name ) : QWidget( _parent ), - IntModelView( new ComboBoxModel( NULL, QString::null, true ), this ), + IntModelView( new ComboBoxModel( NULL, QString(), true ), this ), m_menu( this ), m_pressed( false ) { @@ -198,7 +198,7 @@ void ComboBox::paintEvent( QPaintEvent * _pe ) QPixmap * arrow = m_pressed ? s_arrowSelected : s_arrow; - p.drawPixmap( width() - CB_ARROW_BTN_WIDTH + 5, 4, *arrow ); + p.drawPixmap( width() - CB_ARROW_BTN_WIDTH + 3, 4, *arrow ); if( model() && model()->size() > 0 ) { @@ -251,4 +251,3 @@ void ComboBox::setItem( QAction* item ) - diff --git a/src/gui/widgets/ControllerRackView.cpp b/src/gui/widgets/ControllerRackView.cpp index 79e1bafa0..621c41c73 100644 --- a/src/gui/widgets/ControllerRackView.cpp +++ b/src/gui/widgets/ControllerRackView.cpp @@ -176,7 +176,7 @@ void ControllerRackView::onControllerRemoved( Controller * removedController ) if (viewOfRemovedController ) { - m_controllerViews.erase( qFind( m_controllerViews.begin(), + m_controllerViews.erase( std::find( m_controllerViews.begin(), m_controllerViews.end(), viewOfRemovedController ) ); delete viewOfRemovedController; diff --git a/src/gui/widgets/EffectRackView.cpp b/src/gui/widgets/EffectRackView.cpp index c1e36547e..6af490a42 100644 --- a/src/gui/widgets/EffectRackView.cpp +++ b/src/gui/widgets/EffectRackView.cpp @@ -126,7 +126,7 @@ void EffectRackView::moveDown( EffectView* view ) if( view != m_effectViews.last() ) { // moving next effect up is the same - moveUp( *( qFind( m_effectViews.begin(), m_effectViews.end(), view ) + 1 ) ); + moveUp( *( std::find( m_effectViews.begin(), m_effectViews.end(), view ) + 1 ) ); } } @@ -136,7 +136,7 @@ void EffectRackView::moveDown( EffectView* view ) void EffectRackView::deletePlugin( EffectView* view ) { Effect * e = view->effect(); - m_effectViews.erase( qFind( m_effectViews.begin(), m_effectViews.end(), view ) ); + m_effectViews.erase( std::find( m_effectViews.begin(), m_effectViews.end(), view ) ); delete view; fxChain()->removeEffect( e ); e->deleteLater(); diff --git a/src/gui/widgets/EffectView.cpp b/src/gui/widgets/EffectView.cpp index a4600155b..a159eedf9 100644 --- a/src/gui/widgets/EffectView.cpp +++ b/src/gui/widgets/EffectView.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include "EffectView.h" #include "DummyEffect.h" @@ -49,13 +50,13 @@ EffectView::EffectView( Effect * _model, QWidget * _parent ) : m_controlView( NULL ) { setFixedSize( 210, 60 ); - + // Disable effects that are of type "DummyEffect" bool isEnabled = !dynamic_cast( effect() ); m_bypass = new LedCheckBox( this, "", isEnabled ? LedCheckBox::Green : LedCheckBox::Red ); m_bypass->move( 3, 3 ); m_bypass->setEnabled( isEnabled ); - + ToolTip::add( m_bypass, tr( "On/Off" ) ); @@ -69,14 +70,14 @@ EffectView::EffectView( Effect * _model, QWidget * _parent ) : m_autoQuit = new TempoSyncKnob( knobBright_26, this ); m_autoQuit->setLabel( tr( "DECAY" ) ); m_autoQuit->move( 60, 5 ); - m_autoQuit->setEnabled( isEnabled ); + m_autoQuit->setEnabled( isEnabled && !effect()->m_autoQuitDisabled ); m_autoQuit->setHintText( tr( "Time:" ), "ms" ); m_gate = new Knob( knobBright_26, this ); m_gate->setLabel( tr( "GATE" ) ); m_gate->move( 93, 5 ); - m_gate->setEnabled( isEnabled ); + m_gate->setEnabled( isEnabled && !effect()->m_autoQuitDisabled ); m_gate->setHintText( tr( "Gate:" ), "" ); @@ -96,8 +97,15 @@ EffectView::EffectView( Effect * _model, QWidget * _parent ) : if( m_controlView ) { m_subWindow = gui->mainWindow()->addWindowedWidget( m_controlView ); - m_subWindow->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ); - m_subWindow->setFixedSize( m_subWindow->size() ); + + if ( !m_controlView->isResizable() ) + { + m_subWindow->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ); + if (m_subWindow->layout()) + { + m_subWindow->layout()->setSizeConstraint(QLayout::SetFixedSize); + } + } Qt::WindowFlags flags = m_subWindow->windowFlags(); flags &= ~Qt::WindowMaximizeButtonHint; @@ -120,18 +128,7 @@ EffectView::EffectView( Effect * _model, QWidget * _parent ) : EffectView::~EffectView() { - -#ifdef LMMS_BUILD_LINUX - delete m_subWindow; -#else - if( m_subWindow ) - { - // otherwise on win32 build VST GUI can get lost - m_subWindow->hide(); - } -#endif - } diff --git a/src/gui/widgets/EnvelopeAndLfoView.cpp b/src/gui/widgets/EnvelopeAndLfoView.cpp index fcbfa9424..4635dc831 100644 --- a/src/gui/widgets/EnvelopeAndLfoView.cpp +++ b/src/gui/widgets/EnvelopeAndLfoView.cpp @@ -419,9 +419,9 @@ void EnvelopeAndLfoView::paintEvent( QPaintEvent * ) p.fillRect( x5, y_base - 1, 2, 2, end_points_color ); - int LFO_GRAPH_W = s_lfoGraph->width() - 6; // substract border - int LFO_GRAPH_H = s_lfoGraph->height() - 6; // substract border - int graph_x_base = LFO_GRAPH_X + 3; + int LFO_GRAPH_W = s_lfoGraph->width() - 3; // subtract border + int LFO_GRAPH_H = s_lfoGraph->height() - 6; // subtract border + int graph_x_base = LFO_GRAPH_X + 2; int graph_y_base = LFO_GRAPH_Y + 3 + LFO_GRAPH_H / 2; const float frames_for_graph = SECS_PER_LFO_OSCILLATION * diff --git a/src/gui/widgets/FadeButton.cpp b/src/gui/widgets/FadeButton.cpp index d4244701a..b633286b1 100644 --- a/src/gui/widgets/FadeButton.cpp +++ b/src/gui/widgets/FadeButton.cpp @@ -35,16 +35,21 @@ const float FadeDuration = 300; -FadeButton::FadeButton( const QColor & _normal_color, - const QColor & _activated_color, QWidget * _parent ) : +FadeButton::FadeButton(const QColor & _normal_color, + const QColor & _activated_color, + const QColor & holdColor, + QWidget * _parent) : QAbstractButton( _parent ), m_stateTimer(), + m_releaseTimer(), m_normalColor( _normal_color ), - m_activatedColor( _activated_color ) + m_activatedColor( _activated_color ), + m_holdColor( holdColor ) { - setAttribute( Qt::WA_OpaquePaintEvent, true ); - setCursor( QCursor( embed::getIconPixmap( "hand" ), 3, 3 ) ); - setFocusPolicy( Qt::NoFocus ); + setAttribute(Qt::WA_OpaquePaintEvent, true); + setCursor(QCursor(embed::getIconPixmap("hand"), 3, 3)); + setFocusPolicy(Qt::NoFocus); + activeNotes = 0; } @@ -54,7 +59,7 @@ FadeButton::~FadeButton() { } -void FadeButton::setActiveColor( const QColor & activated_color ) +void FadeButton::setActiveColor(const QColor & activated_color) { m_activatedColor = activated_color; } @@ -65,63 +70,104 @@ void FadeButton::setActiveColor( const QColor & activated_color ) void FadeButton::activate() { m_stateTimer.restart(); + activeNotes++; signalUpdate(); } -void FadeButton::customEvent( QEvent * ) +void FadeButton::noteEnd() +{ + if (activeNotes <= 0) + { + qWarning("noteEnd() triggered without a corresponding activate()!"); + activeNotes = 0; + } + else + { + activeNotes--; + } + + if (activeNotes == 0) + { + m_releaseTimer.restart(); + } + + signalUpdate(); +} + + + + +void FadeButton::customEvent(QEvent *) { update(); } - -void FadeButton::paintEvent( QPaintEvent * _pe ) +void FadeButton::paintEvent(QPaintEvent * _pe) { QColor col = m_normalColor; - if( ! m_stateTimer.isNull() && m_stateTimer.elapsed() < FadeDuration ) + + if(!m_stateTimer.isNull() && m_stateTimer.elapsed() < FadeDuration) { - const float state = 1 - m_stateTimer.elapsed() / FadeDuration; - const int r = (int)( m_normalColor.red() * - ( 1.0f - state ) + - m_activatedColor.red() * state ); - const int g = (int)( m_normalColor.green() * - ( 1.0f - state ) + - m_activatedColor.green() * state ); - const int b = (int)( m_normalColor.blue() * - ( 1.0f - state ) + - m_activatedColor.blue() * state ); - col.setRgb( r, g, b ); - QTimer::singleShot( 20, this, SLOT( update() ) ); + // The first part of the fade, when a note is triggered. + col = fadeToColor(m_activatedColor, m_holdColor, m_stateTimer, FadeDuration); + QTimer::singleShot(20, this, SLOT(update())); + } + else if (!m_stateTimer.isNull() + && m_stateTimer.elapsed() >= FadeDuration + && activeNotes > 0) + { + // The fade is done, but at least one note is still held. + col = m_holdColor; + } + else if (!m_releaseTimer.isNull() && m_releaseTimer.elapsed() < FadeDuration) + { + // Last note just ended. Fade to default color. + col = fadeToColor(m_holdColor, m_normalColor, m_releaseTimer, FadeDuration); + QTimer::singleShot(20, this, SLOT(update())); + } + else + { + // No fade, no notes. Set to default color. + col = m_normalColor; } - QPainter p( this ); - p.fillRect( rect(), col ); + QPainter p(this); + p.fillRect(rect(), col); int w = rect().right(); int h = rect().bottom(); - p.setPen( m_normalColor.darker(130) ); - p.drawLine( w, 1, w, h ); - p.drawLine( 1, h, w, h ); - p.setPen( m_normalColor.lighter(130) ); - p.drawLine( 0, 0, 0, h-1 ); - p.drawLine( 0, 0, w, 0 ); + p.setPen(m_normalColor.darker(130)); + p.drawLine(w, 1, w, h); + p.drawLine(1, h, w, h); + p.setPen(m_normalColor.lighter(130)); + p.drawLine(0, 0, 0, h-1); + p.drawLine(0, 0, w, 0); } +QColor FadeButton::fadeToColor(QColor startCol, QColor endCol, QTime timer, float duration) +{ + QColor col; + + const float state = 1 - timer.elapsed() / duration; + const int r = (int)(endCol.red() * (1.0f - state) + + startCol.red() * state); + const int g = (int)(endCol.green() * (1.0f - state) + + startCol.green() * state); + const int b = (int)(endCol.blue() * (1.0f - state) + + startCol.blue() * state); + col.setRgb(r, g, b); + + return col; +} void FadeButton::signalUpdate() { - QApplication::postEvent( this, new updateEvent() ); + QApplication::postEvent(this, new updateEvent()); } - - - - - - - diff --git a/src/gui/widgets/FxLine.cpp b/src/gui/widgets/FxLine.cpp index d30ff5a7c..3314301fd 100644 --- a/src/gui/widgets/FxLine.cpp +++ b/src/gui/widgets/FxLine.cpp @@ -264,6 +264,7 @@ void FxLine::renameChannel() void FxLine::renameFinished() { m_inRename = false; + m_renameLineEdit->deselect(); m_renameLineEdit->setReadOnly( true ); m_renameLineEdit->setFixedWidth( 65 ); m_lcd->show(); diff --git a/src/gui/widgets/FxLineLcdSpinBox.cpp b/src/gui/widgets/FxLineLcdSpinBox.cpp new file mode 100644 index 000000000..bfe4a9637 --- /dev/null +++ b/src/gui/widgets/FxLineLcdSpinBox.cpp @@ -0,0 +1,66 @@ +/* + * FxLineLcdSpinBox.cpp - a specialization of LcdSpnBox for setting FX channels + * + * Copyright (c) 2004-2014 Tobias Doerffel + * + * 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. + * + */ + +#include "FxLineLcdSpinBox.h" + +#include "CaptionMenu.h" +#include "FxMixerView.h" +#include "GuiApplication.h" +#include "Track.h" + +void FxLineLcdSpinBox::setTrackView(TrackView * tv) +{ + m_tv = tv; +} + +void FxLineLcdSpinBox::mouseDoubleClickEvent(QMouseEvent* event) +{ + gui->fxMixerView()->setCurrentFxLine(model()->value()); + + gui->fxMixerView()->parentWidget()->show(); + gui->fxMixerView()->show();// show fxMixer window + gui->fxMixerView()->setFocus();// set focus to fxMixer window + //engine::getFxMixerView()->raise(); +} + +void FxLineLcdSpinBox::contextMenuEvent(QContextMenuEvent* event) +{ + // for the case, the user clicked right while pressing left mouse- + // button, the context-menu appears while mouse-cursor is still hidden + // and it isn't shown again until user does something which causes + // an QApplication::restoreOverrideCursor()-call... + mouseReleaseEvent(nullptr); + + QPointer contextMenu = new CaptionMenu(model()->displayName(), this); + + if (QMenu *fxMenu = m_tv->createFxMenu( + tr("Assign to:"), tr("New FX Channel"))) + { + contextMenu->addMenu(fxMenu); + + contextMenu->addSeparator(); + } + addDefaultActions(contextMenu); + contextMenu->exec(QCursor::pos()); +} diff --git a/src/gui/widgets/Graph.cpp b/src/gui/widgets/Graph.cpp index ed57dcea6..4710089dd 100644 --- a/src/gui/widgets/Graph.cpp +++ b/src/gui/widgets/Graph.cpp @@ -510,7 +510,7 @@ void graphModel::setSampleAt( int x, float val ) void graphModel::setSamples( const float * _samples ) { - qCopy( _samples, _samples + length(), m_samples.begin()); + std::copy( _samples, _samples + length(), m_samples.begin()); emit samplesChanged( 0, length()-1 ); } @@ -635,13 +635,14 @@ void graphModel::smoothNonCyclic() emit samplesChanged(0, length()-1); } -//makes a cyclic convolution. -void graphModel::convolve(const float *convolution, const int convolutionLength, const int centerOffset) +void graphModel::convolve(const float *convolution, + const int convolutionLength, const int centerOffset) { // store values in temporary array QVector temp = m_samples; const int graphLength = length(); float sum; + // make a cyclic convolution for ( int i = 0; i < graphLength; i++ ) { sum = 0; @@ -720,6 +721,15 @@ void graphModel::clear() } +// Clear any part of the graph that isn't displayed +void graphModel::clearInvisible() +{ + const int graph_length = length(); + const int full_graph_length = m_samples.size(); + for( int i = graph_length; i < full_graph_length; i++ ) + m_samples[i] = 0; + emit samplesChanged( graph_length, full_graph_length - 1 ); +} void graphModel::drawSampleAt( int x, float val ) { 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/gui/widgets/Knob.cpp b/src/gui/widgets/Knob.cpp index 3d1828fe5..c3e26ae11 100644 --- a/src/gui/widgets/Knob.cpp +++ b/src/gui/widgets/Knob.cpp @@ -41,6 +41,7 @@ #include "embed.h" #include "gui_templates.h" #include "GuiApplication.h" +#include "LocaleHelper.h" #include "MainWindow.h" #include "ProjectJournal.h" #include "Song.h" @@ -558,7 +559,7 @@ void Knob::dropEvent( QDropEvent * _de ) QString val = StringPairDrag::decodeValue( _de ); if( type == "float_value" ) { - model()->setValue( val.toFloat() ); + model()->setValue( LocaleHelper::toFloat(val) ); _de->accept(); } else if( type == "automatable_model" ) diff --git a/src/gui/widgets/LadspaControlView.cpp b/src/gui/widgets/LadspaControlView.cpp index 800eae4e9..39ed1c3ea 100644 --- a/src/gui/widgets/LadspaControlView.cpp +++ b/src/gui/widgets/LadspaControlView.cpp @@ -60,7 +60,7 @@ LadspaControlView::LadspaControlView( QWidget * _parent, case TOGGLED: { LedCheckBox * toggle = new LedCheckBox( - m_ctl->port()->name, this, QString::null, LedCheckBox::Green ); + m_ctl->port()->name, this, QString(), LedCheckBox::Green ); toggle->setModel( m_ctl->toggledModel() ); layout->addWidget( toggle ); if( link != NULL ) diff --git a/src/gui/widgets/PixmapButton.cpp b/src/gui/widgets/PixmapButton.cpp index 9858c221d..eb2553cf7 100644 --- a/src/gui/widgets/PixmapButton.cpp +++ b/src/gui/widgets/PixmapButton.cpp @@ -134,11 +134,11 @@ QSize PixmapButton::sizeHint() const { if( ( model() != NULL && model()->value() ) || m_pressed ) { - return m_activePixmap.size(); + return m_activePixmap.size() / devicePixelRatio(); } else { - return m_inactivePixmap.size(); + return m_inactivePixmap.size() / devicePixelRatio(); } } diff --git a/src/gui/widgets/ProjectNotes.cpp b/src/gui/widgets/ProjectNotes.cpp index d8d6636c4..7fc35b446 100644 --- a/src/gui/widgets/ProjectNotes.cpp +++ b/src/gui/widgets/ProjectNotes.cpp @@ -115,56 +115,31 @@ void ProjectNotes::setupActions() a = new QAction( embed::getIconPixmap( "edit_undo" ), tr( "&Undo" ), this ); - a->setShortcut( tr( "%1+Z" ).arg( - #ifdef LMMS_BUILD_APPLE - "⌘") ); - #else - "Ctrl") ); - #endif + a->setShortcut( tr( "%1+Z" ).arg(UI_CTRL_KEY) ); connect( a, SIGNAL( triggered() ), m_edit, SLOT( undo() ) ); tb->addAction( a ); a = new QAction( embed::getIconPixmap( "edit_redo" ), tr( "&Redo" ), this ); - a->setShortcut( tr( "%1+Y" ).arg( - #ifdef LMMS_BUILD_APPLE - "⌘") ); - #else - "Ctrl") ); - #endif + a->setShortcut( tr( "%1+Y" ).arg(UI_CTRL_KEY) ); connect( a, SIGNAL( triggered() ), m_edit, SLOT( redo() ) ); tb->addAction( a ); a = new QAction( embed::getIconPixmap( "edit_copy" ), tr( "&Copy" ), this ); - a->setShortcut( tr( "%1+C" ).arg( - #ifdef LMMS_BUILD_APPLE - "⌘") ); - #else - "Ctrl") ); - #endif + a->setShortcut( tr( "%1+C" ).arg(UI_CTRL_KEY) ); connect( a, SIGNAL( triggered() ), m_edit, SLOT( copy() ) ); tb->addAction( a ); a = new QAction( embed::getIconPixmap( "edit_cut" ), tr( "Cu&t" ), this ); - a->setShortcut( tr( "%1+X" ).arg( - #ifdef LMMS_BUILD_APPLE - "⌘") ); - #else - "Ctrl") ); - #endif + a->setShortcut( tr( "%1+X" ).arg(UI_CTRL_KEY) ); connect( a, SIGNAL( triggered() ), m_edit, SLOT( cut() ) ); tb->addAction( a ); a = new QAction( embed::getIconPixmap( "edit_paste" ), tr( "&Paste" ), this ); - a->setShortcut( tr( "%1+V" ).arg( - #ifdef LMMS_BUILD_APPLE - "⌘") ); - #else - "Ctrl") ); - #endif + a->setShortcut( tr( "%1+V" ).arg(UI_CTRL_KEY) ); connect( a, SIGNAL( triggered() ), m_edit, SLOT( paste() ) ); tb->addAction( a ); @@ -194,24 +169,14 @@ void ProjectNotes::setupActions() m_actionTextBold = new QAction( embed::getIconPixmap( "text_bold" ), tr( "&Bold" ), this ); - m_actionTextBold->setShortcut( tr( "%1+B" ).arg( - #ifdef LMMS_BUILD_APPLE - "⌘") ); - #else - "Ctrl") ); - #endif + m_actionTextBold->setShortcut( tr( "%1+B" ).arg(UI_CTRL_KEY) ); m_actionTextBold->setCheckable( true ); connect( m_actionTextBold, SIGNAL( triggered() ), this, SLOT( textBold() ) ); m_actionTextItalic = new QAction( embed::getIconPixmap( "text_italic" ), tr( "&Italic" ), this ); - m_actionTextItalic->setShortcut( tr( "%1+I" ).arg( - #ifdef LMMS_BUILD_APPLE - "⌘") ); - #else - "Ctrl") ); - #endif + m_actionTextItalic->setShortcut( tr( "%1+I" ).arg(UI_CTRL_KEY) ); m_actionTextItalic->setCheckable( true ); connect( m_actionTextItalic, SIGNAL( triggered() ), this, SLOT( textItalic() ) ); @@ -219,12 +184,7 @@ void ProjectNotes::setupActions() m_actionTextUnderline = new QAction( embed::getIconPixmap( "text_under" ), tr( "&Underline" ), this ); - m_actionTextUnderline->setShortcut( tr( "%1+U" ).arg( - #ifdef LMMS_BUILD_APPLE - "⌘") ); - #else - "Ctrl") ); - #endif + m_actionTextUnderline->setShortcut( tr( "%1+U" ).arg(UI_CTRL_KEY) ); m_actionTextUnderline->setCheckable( true ); connect( m_actionTextUnderline, SIGNAL( triggered() ), this, SLOT( textUnderline() ) ); @@ -236,12 +196,7 @@ void ProjectNotes::setupActions() m_actionAlignLeft = new QAction( embed::getIconPixmap( "text_left" ), tr( "&Left" ), m_edit ); - m_actionAlignLeft->setShortcut( tr( "%1+L" ).arg( - #ifdef LMMS_BUILD_APPLE - "⌘") ); - #else - "Ctrl") ); - #endif + m_actionAlignLeft->setShortcut( tr( "%1+L" ).arg(UI_CTRL_KEY) ); m_actionAlignLeft->setCheckable( true ); grp->addAction( m_actionAlignLeft ); @@ -249,36 +204,21 @@ void ProjectNotes::setupActions() "text_center" ), tr( "C&enter" ), m_edit ); m_actionAlignCenter->setShortcutContext( Qt::WidgetShortcut ); - m_actionAlignCenter->setShortcut( tr( "%1+E" ).arg( - #ifdef LMMS_BUILD_APPLE - "⌘") ); - #else - "Ctrl") ); - #endif + m_actionAlignCenter->setShortcut( tr( "%1+E" ).arg(UI_CTRL_KEY) ); m_actionAlignCenter->setCheckable( true ); grp->addAction( m_actionAlignCenter ); m_actionAlignRight = new QAction( embed::getIconPixmap( "text_right" ), tr( "&Right" ), m_edit ); m_actionAlignRight->setShortcutContext( Qt::WidgetShortcut ); - m_actionAlignRight->setShortcut( tr( "%1+R" ).arg( - #ifdef LMMS_BUILD_APPLE - "⌘") ); - #else - "Ctrl") ); - #endif + m_actionAlignRight->setShortcut( tr( "%1+R" ).arg(UI_CTRL_KEY) ); m_actionAlignRight->setCheckable( true ); grp->addAction( m_actionAlignRight ); m_actionAlignJustify = new QAction( embed::getIconPixmap( "text_block" ), tr( "&Justify" ), m_edit ); - m_actionAlignJustify->setShortcut( tr( "%1+J" ).arg( - #ifdef LMMS_BUILD_APPLE - "⌘") ); - #else - "Ctrl") ); - #endif + m_actionAlignJustify->setShortcut( tr( "%1+J" ).arg(UI_CTRL_KEY) ); m_actionAlignJustify->setCheckable( true ); grp->addAction( m_actionAlignJustify ); 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() ) ) ); - } - } } diff --git a/src/gui/widgets/SideBar.cpp b/src/gui/widgets/SideBar.cpp index 01ea58919..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; @@ -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); } diff --git a/src/gui/widgets/StepRecorderWidget.cpp b/src/gui/widgets/StepRecorderWidget.cpp new file mode 100644 index 000000000..a546c2a2c --- /dev/null +++ b/src/gui/widgets/StepRecorderWidget.cpp @@ -0,0 +1,155 @@ +/* + * StepRecoderWidget.cpp - widget that provide gui markers for step recording + * + * 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. + * + */ + +#include "StepRecorderWidget.h" +#include "TextFloat.h" +#include "embed.h" + +StepRecorderWidget::StepRecorderWidget( + QWidget * parent, + const int ppb, + const int marginTop, + const int marginBottom, + const int marginLeft, + const int marginRight) : + QWidget(parent), + m_marginTop(marginTop), + m_marginBottom(marginBottom), + m_marginLeft(marginLeft), + m_marginRight(marginRight) +{ + const QColor baseColor = QColor(255, 0, 0);// QColor(204, 163, 0); // Orange + m_colorLineEnd = baseColor.lighter(150); + m_colorLineStart = baseColor.darker(120); + + setAttribute(Qt::WA_NoSystemBackground, true); + setPixelsPerBar(ppb); + + m_top = m_marginTop; + m_left = m_marginLeft; +} + +void StepRecorderWidget::setPixelsPerBar(int ppb) +{ + m_ppb = ppb; +} + +void StepRecorderWidget::setCurrentPosition(MidiTime currentPosition) +{ + m_currentPosition = currentPosition; +} + +void StepRecorderWidget::setBottomMargin(const int marginBottom) +{ + m_marginBottom = marginBottom; +} + +void StepRecorderWidget::setStartPosition(MidiTime pos) +{ + m_curStepStartPos = pos; +} + +void StepRecorderWidget::setEndPosition(MidiTime pos) +{ + m_curStepEndPos = pos; + emit positionChanged(m_curStepEndPos); +} + +void StepRecorderWidget::showHint() +{ + TextFloat::displayMessage(tr( "Hint" ), tr("Move recording curser using arrows"), + embed::getIconPixmap("hint")); +} + +void StepRecorderWidget::setStepsLength(MidiTime stepsLength) +{ + m_stepsLength = stepsLength; +} + +void StepRecorderWidget::paintEvent(QPaintEvent * pe) +{ + QPainter painter(this); + + updateBoundaries(); + + move(0, 0); + + //draw steps ruler + painter.setPen(m_colorLineEnd); + + MidiTime curPos = m_curStepEndPos; + int x = xCoordOfTick(curPos); + while(x <= m_right) + { + const int w = 2; + const int h = 4; + painter.drawRect(x - 1, m_top, w, h); + curPos += m_stepsLength; + x = xCoordOfTick(curPos); + } + + //draw current step start/end position lines + if(m_curStepStartPos != m_curStepEndPos) + { + drawVerLine(&painter, m_curStepStartPos, m_colorLineStart, m_top, m_bottom); + } + + drawVerLine(&painter, m_curStepEndPos, m_colorLineEnd, m_top, m_bottom); + + //if the line is adjacent to the keyboard at the left - it cannot be seen. + //add another line to make it clearer + if(m_curStepEndPos == 0) + { + drawVerLine(&painter, xCoordOfTick(m_curStepEndPos) + 1, m_colorLineEnd, m_top, m_bottom); + } +} + +int StepRecorderWidget::xCoordOfTick(int tick) +{ + return m_marginLeft + ((tick - m_currentPosition) * m_ppb / MidiTime::ticksPerBar()); +} + + +void StepRecorderWidget::drawVerLine(QPainter* painter, int x, const QColor& color, int top, int bottom) +{ + if(x >= m_marginLeft && x <= (width() - m_marginRight)) + { + painter->setPen(color); + painter->drawLine( x, top, x, bottom ); + } +} + +void StepRecorderWidget::drawVerLine(QPainter* painter, const MidiTime& pos, const QColor& color, int top, int bottom) +{ + drawVerLine(painter, xCoordOfTick(pos), color, top, bottom); +} + +void StepRecorderWidget::updateBoundaries() +{ + setFixedSize(parentWidget()->size()); + + m_bottom = height() - m_marginBottom; + m_right = width() - m_marginTop; + + //(no need to change top and left as they are static) +} + diff --git a/src/gui/widgets/TabWidget.cpp b/src/gui/widgets/TabWidget.cpp index f06710098..22d322612 100644 --- a/src/gui/widgets/TabWidget.cpp +++ b/src/gui/widgets/TabWidget.cpp @@ -34,8 +34,10 @@ #include "gui_templates.h" #include "embed.h" -TabWidget::TabWidget( const QString & caption, QWidget * parent, bool usePixmap ) : +TabWidget::TabWidget(const QString & caption, QWidget * parent, bool usePixmap, + bool resizable) : QWidget( parent ), + m_resizable( resizable ), m_activeTab( 0 ), m_caption( caption ), m_usePixmap( usePixmap ), @@ -81,7 +83,10 @@ void TabWidget::addTab( QWidget * w, const QString & name, const char *pixmap, i m_widgets[idx] = d; // Position tab's window - w->setFixedSize( width() - 4, height() - m_tabbarHeight ); + if (!m_resizable) + { + w->setFixedSize( width() - 4, height() - m_tabbarHeight ); + } w->move( 2, m_tabbarHeight - 1 ); w->hide(); @@ -189,17 +194,19 @@ void TabWidget::mousePressEvent( QMouseEvent * me ) void TabWidget::resizeEvent( QResizeEvent * ) { - for( widgetStack::iterator it = m_widgets.begin(); - it != m_widgets.end(); ++it ) + if (!m_resizable) { - ( *it ).w->setFixedSize( width() - 4, height() - m_tabbarHeight ); + for ( widgetStack::iterator it = m_widgets.begin(); + it != m_widgets.end(); ++it ) + { + ( *it ).w->setFixedSize( width() - 4, height() - m_tabbarHeight ); + } } } - void TabWidget::paintEvent( QPaintEvent * pe ) { QPainter p( this ); @@ -284,7 +291,7 @@ void TabWidget::wheelEvent( QWheelEvent * we ) if( we->y() > m_tabheight ) { return; - } + } we->accept(); int dir = ( we->delta() < 0 ) ? 1 : -1; @@ -300,6 +307,54 @@ void TabWidget::wheelEvent( QWheelEvent * we ) setActiveTab( tab ); } + + + +// Let parent widgets know how much space this tab widget needs +QSize TabWidget::minimumSizeHint() const +{ + if (m_resizable) + { + int maxWidth = 0, maxHeight = 0; + for ( widgetStack::const_iterator it = m_widgets.begin(); + it != m_widgets.end(); ++it ) + { + maxWidth = std::max(maxWidth, it->w->minimumSizeHint().width()); + maxHeight = std::max(maxHeight, it->w->minimumSizeHint().height()); + } + // "-1" : + // in "addTab", under "Position tab's window", the widget is + // moved up by 1 pixel + return QSize(maxWidth + 4, maxHeight + m_tabbarHeight - 1); + } + else { return QWidget::minimumSizeHint(); } +} + + + + +QSize TabWidget::sizeHint() const +{ + if (m_resizable) + { + int maxWidth = 0, maxHeight = 0; + for ( widgetStack::const_iterator it = m_widgets.begin(); + it != m_widgets.end(); ++it ) + { + maxWidth = std::max(maxWidth, it->w->sizeHint().width()); + maxHeight = std::max(maxHeight, it->w->sizeHint().height()); + } + // "-1" : + // in "addTab", under "Position tab's window", the widget is + // moved up by 1 pixel + return QSize(maxWidth + 4, maxHeight + m_tabbarHeight - 1); + } + else { return QWidget::sizeHint(); } +} + + + + // Return the color to be used to draw a TabWidget's title text (if any) QColor TabWidget::tabTitleText() const { 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 ); } 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/gui/widgets/TrackLabelButton.cpp b/src/gui/widgets/TrackLabelButton.cpp index db310a05e..361db740e 100644 --- a/src/gui/widgets/TrackLabelButton.cpp +++ b/src/gui/widgets/TrackLabelButton.cpp @@ -195,9 +195,15 @@ void TrackLabelButton::paintEvent( QPaintEvent * _pe ) InstrumentTrack * it = dynamic_cast( m_trackView->getTrack() ); const PixmapLoader * pl; + auto get_logo = [](InstrumentTrack* it) -> const PixmapLoader* + { + return it->instrument()->key().isValid() + ? it->instrument()->key().logo() + : it->instrument()->descriptor()->logo; + }; if( it && it->instrument() && it->instrument()->descriptor() && - ( pl = it->instrument()->descriptor()->logo ) ) + ( pl = get_logo(it) ) ) { if( pl->pixmapName() != m_iconName ) { diff --git a/src/gui/widgets/VisualizationWidget.cpp b/src/gui/widgets/VisualizationWidget.cpp index 00521f7bc..635f96896 100644 --- a/src/gui/widgets/VisualizationWidget.cpp +++ b/src/gui/widgets/VisualizationWidget.cpp @@ -43,7 +43,10 @@ VisualizationWidget::VisualizationWidget( const QPixmap & _bg, QWidget * _p, QWidget( _p ), s_background( _bg ), m_points( new QPointF[Engine::mixer()->framesPerPeriod()] ), - m_active( false ) + m_active( false ), + m_normalColor(71, 253, 133), + m_warningColor(255, 192, 64), + m_clippingColor(255, 64, 64) { setFixedSize( s_background.width(), s_background.height() ); setAttribute( Qt::WA_OpaquePaintEvent, true ); @@ -109,6 +112,35 @@ void VisualizationWidget::setActive( bool _active ) } +QColor const & VisualizationWidget::normalColor() const +{ + return m_normalColor; +} + +void VisualizationWidget::setNormalColor(QColor const & normalColor) +{ + m_normalColor = normalColor; +} + +QColor const & VisualizationWidget::warningColor() const +{ + return m_warningColor; +} + +void VisualizationWidget::setWarningColor(QColor const & warningColor) +{ + m_warningColor = warningColor; +} + +QColor const & VisualizationWidget::clippingColor() const +{ + return m_clippingColor; +} + +void VisualizationWidget::setClippingColor(QColor const & clippingColor) +{ + m_clippingColor = clippingColor; +} void VisualizationWidget::paintEvent( QPaintEvent * ) @@ -122,49 +154,32 @@ void VisualizationWidget::paintEvent( QPaintEvent * ) Mixer const * mixer = Engine::mixer(); float master_output = mixer->masterGain(); - int w = width()-4; - const float half_h = -( height() - 6 ) / 3.0 * master_output - 1; - int x_base = 2; - const float y_base = height()/2 - 0.5f; - -// p.setClipRect( 2, 2, w, height()-4 ); - const fpp_t frames = mixer->framesPerPeriod(); - float peakLeft; - float peakRight; - mixer->getPeakValues( m_buffer, frames, peakLeft, peakRight ); - const float max_level = qMax( peakLeft, peakRight ); + Mixer::StereoSample peakValues = mixer->getPeakValues(m_buffer, frames); + const float max_level = qMax( peakValues.left, peakValues.right ); - // and set color according to that... - if( max_level * master_output < 0.9 ) - { - p.setPen( QColor( 71, 253, 133 ) ); - } - else if( max_level * master_output < 1.0 ) - { - p.setPen( QColor( 255, 192, 64 ) ); - } - else - { - p.setPen( QColor( 255, 64, 64 ) ); - } + // Set the color of the line according to the maximum level + float const maxLevelWithAppliedMasterGain = max_level * master_output; + p.setPen(QPen(determineLineColor(maxLevelWithAppliedMasterGain), 0.7)); - p.setPen( QPen( p.pen().color(), 0.7 ) ); - - const float xd = (float) w / frames; p.setRenderHint( QPainter::Antialiasing ); // now draw all that stuff + int w = width() - 4; + const qreal xd = static_cast(w) / frames; + const qreal half_h = -( height() - 6 ) / 3.0 * static_cast(master_output) - 1; + int x_base = 2; + const qreal y_base = height() / 2 - 0.5; + for( ch_cnt_t ch = 0; ch < DEFAULT_CHANNELS; ++ch ) { for( int frame = 0; frame < frames; ++frame ) { + sample_t const clippedSample = Mixer::clip(m_buffer[frame][ch]); m_points[frame] = QPointF( - x_base + (float) frame * xd, - y_base + ( Mixer::clip( - m_buffer[frame][ch] ) * - half_h ) ); + x_base + static_cast(frame) * xd, + y_base + ( static_cast(clippedSample) * half_h ) ); } p.drawPolyline( m_points, frames ); } @@ -189,7 +204,21 @@ void VisualizationWidget::mousePressEvent( QMouseEvent * _me ) } - +QColor const & VisualizationWidget::determineLineColor(float level) const +{ + if( level < 0.9f ) + { + return normalColor(); + } + else if( level <= 1.0f ) + { + return warningColor(); + } + else + { + return clippingColor(); + } +} diff --git a/src/lmmsconfig.h.in b/src/lmmsconfig.h.in index 02d07f1e4..3ea9d749c 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 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 c37c1466f..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 ); @@ -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 ) ); @@ -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 ), @@ -635,5 +635,6 @@ bool BBTrackView::close() void BBTrackView::clickedTrackLabel() { Engine::getBBTrackContainer()->setCurrentBB( m_bbTrack->index() ); - gui->getBBEditor()->show(); + gui->getBBEditor()->parentWidget()->show(); + gui->getBBEditor()->setFocus( Qt::ActiveWindowFocusReason ); } diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 19bb044b9..3e41141af 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -47,6 +47,7 @@ #include "EffectRackView.h" #include "embed.h" #include "FileBrowser.h" +#include "FxLineLcdSpinBox.h" #include "FxMixer.h" #include "FxMixerView.h" #include "GuiApplication.h" @@ -129,11 +130,16 @@ InstrumentTrack::InstrumentTrack( TrackContainer* tc ) : setName( tr( "Default preset" ) ); - connect( &m_baseNoteModel, SIGNAL( dataChanged() ), this, SLOT( updateBaseNote() ) ); - connect( &m_pitchModel, SIGNAL( dataChanged() ), this, SLOT( updatePitch() ) ); - connect( &m_pitchRangeModel, SIGNAL( dataChanged() ), this, SLOT( updatePitchRange() ) ); - connect( &m_effectChannelModel, SIGNAL( dataChanged() ), this, SLOT( updateEffectChannel() ) ); - connect( &m_useGrooveModel, SIGNAL( dataChanged() ), this, SLOT( updateGroove() ) ); + connect( &m_baseNoteModel, SIGNAL( dataChanged() ), + this, SLOT( updateBaseNote() ), Qt::DirectConnection ); + connect( &m_pitchModel, SIGNAL( dataChanged() ), + this, SLOT( updatePitch() ), Qt::DirectConnection ); + connect( &m_pitchRangeModel, SIGNAL( dataChanged() ), + this, SLOT( updatePitchRange() ), Qt::DirectConnection ); + connect( &m_effectChannelModel, SIGNAL( dataChanged() ), + this, SLOT( updateEffectChannel() ), Qt::DirectConnection ); + connect( &m_useGrooveModel, SIGNAL( dataChanged() ), + this, SLOT( updateGroove() ), Qt::DirectConnection ); } @@ -425,6 +431,7 @@ void InstrumentTrack::processOutEvent( const MidiEvent& event, const MidiTime& t m_instrument->handleMidiEvent( MidiEvent( MidiNoteOff, midiPort()->realOutputChannel(), key, 0 ), time, offset ); } m_midiNotesMutex.unlock(); + emit endNote(); break; default: @@ -504,7 +511,7 @@ QString InstrumentTrack::instrumentName() const { return m_instrument->displayName(); } - return QString::null; + return QString(); } @@ -595,7 +602,7 @@ int InstrumentTrack::masterKey( int _midi_key ) const { int key = baseNote(); - return tLimit( _midi_key - ( key - DefaultKey ), 0, NumKeys ); + return qBound( 0, _midi_key - ( key - DefaultKey ), NumKeys ); } @@ -658,8 +665,11 @@ bool InstrumentTrack::play( const MidiTime & _start, const fpp_t _frames, for( tcoVector::Iterator it = tcos.begin(); it != tcos.end(); ++it ) { Pattern* p = dynamic_cast( *it ); - // everything which is not a pattern or muted won't be played - if( p == NULL || ( *it )->isMuted() ) + // everything which is not a pattern won't be played + // A pattern playing in the Piano Roll window will always play + if(p == NULL || + (Engine::getSong()->playMode() != Song::Mode_PlayPattern + && (*it)->isMuted())) { continue; } @@ -690,7 +700,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; @@ -791,13 +801,23 @@ void InstrumentTrack::saveTrackSpecificSettings( QDomDocument& doc, QDomElement { QDomElement i = doc.createElement( "instrument" ); i.setAttribute( "name", m_instrument->descriptor()->name ); - m_instrument->saveState( doc, i ); + QDomElement ins = m_instrument->saveState( doc, i ); + if(m_instrument->key().isValid()) { + ins.appendChild( m_instrument->key().saveXML( doc ) ); + } thisElement.appendChild( i ); } m_soundShaping.saveState( doc, thisElement ); m_noteStacking.saveState( doc, thisElement ); m_arpeggio.saveState( doc, thisElement ); - m_midiPort.saveState( doc, thisElement ); + + // Don't save midi port info if the user chose to. + if (Engine::getSong()->isSavingProject() + && !Engine::getSong()->getSaveOptions().discardMIDIConnections.value()) + { + m_midiPort.saveState( doc, thisElement ); + } + m_audioPort.effects()->saveState( doc, thisElement ); } @@ -853,9 +873,13 @@ void InstrumentTrack::loadTrackSpecificSettings( const QDomElement & thisElement } else if( node.nodeName() == "instrument" ) { + typedef Plugin::Descriptor::SubPluginFeatures::Key PluginKey; + PluginKey key( node.toElement().elementsByTagName( "key" ).item( 0 ).toElement() ); + delete m_instrument; m_instrument = NULL; - m_instrument = Instrument::instantiate( node.toElement().attribute( "name" ), this ); + m_instrument = Instrument::instantiate( + node.toElement().attribute( "name" ), this, &key); m_instrument->restoreState( node.firstChildElement() ); emit instrumentChanged(); @@ -869,7 +893,8 @@ void InstrumentTrack::loadTrackSpecificSettings( const QDomElement & thisElement { delete m_instrument; m_instrument = NULL; - m_instrument = Instrument::instantiate( node.nodeName(), this ); + m_instrument = Instrument::instantiate( + node.nodeName(), this, nullptr, true); if( m_instrument->nodeName() == node.nodeName() ) { m_instrument->restoreState( node.toElement() ); @@ -894,15 +919,20 @@ void InstrumentTrack::setPreviewMode( const bool value ) -Instrument * InstrumentTrack::loadInstrument( const QString & _plugin_name ) +Instrument * InstrumentTrack::loadInstrument(const QString & _plugin_name, + const Plugin::Descriptor::SubPluginFeatures::Key *key, bool keyFromDnd) { + if(keyFromDnd) + Q_ASSERT(!key); + silenceAllNotes( true ); lock(); delete m_instrument; - m_instrument = Instrument::instantiate( _plugin_name, this ); + m_instrument = Instrument::instantiate(_plugin_name, this, + key, keyFromDnd); unlock(); - setName( m_instrument->displayName() ); + setName(m_instrument->displayName()); emit instrumentChanged(); @@ -1008,6 +1038,8 @@ InstrumentTrackView::InstrumentTrackView( InstrumentTrack * _it, TrackContainerV QPalette::Background), QApplication::palette().color( QPalette::Active, QPalette::BrightText ), + QApplication::palette().color( QPalette::Active, + QPalette::BrightText).darker(), getTrackSettingsWidget() ); m_activityIndicator->setGeometry( widgetWidth-2*24-11, 2, 8, 28 ); @@ -1018,6 +1050,8 @@ InstrumentTrackView::InstrumentTrackView( InstrumentTrack * _it, TrackContainerV this, SLOT( activityIndicatorReleased() ) ); connect( _it, SIGNAL( newNote() ), m_activityIndicator, SLOT( activate() ) ); + connect( _it, SIGNAL( endNote() ), + m_activityIndicator, SLOT( noteEnd() ) ); connect( &_it->m_mutedModel, SIGNAL( dataChanged() ), this, SLOT( muteChanged() ) ); setModel( _it ); @@ -1263,6 +1297,7 @@ void InstrumentTrackView::muteChanged() +//FIXME: This is identical to SampleTrackView::createFxMenu QMenu * InstrumentTrackView::createFxMenu(QString title, QString newFxLabel) { int channelIndex = model()->effectChannelModel()->value(); @@ -1277,8 +1312,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(); @@ -1288,66 +1321,20 @@ 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; } -class fxLineLcdSpinBox : public LcdSpinBox -{ - Q_OBJECT - public: - fxLineLcdSpinBox( int _num_digits, QWidget * _parent, - const QString & _name ) : - LcdSpinBox( _num_digits, _parent, _name ) {} - - protected: - virtual void mouseDoubleClickEvent ( QMouseEvent * _me ) - { - gui->fxMixerView()->setCurrentFxLine( model()->value() ); - - gui->fxMixerView()->parentWidget()->show(); - gui->fxMixerView()->show();// show fxMixer window - gui->fxMixerView()->setFocus();// set focus to fxMixer window - //engine::getFxMixerView()->raise(); - } - - virtual void contextMenuEvent( QContextMenuEvent* event ) - { - // for the case, the user clicked right while pressing left mouse- - // button, the context-menu appears while mouse-cursor is still hidden - // and it isn't shown again until user does something which causes - // an QApplication::restoreOverrideCursor()-call... - mouseReleaseEvent( NULL ); - - QPointer contextMenu = new CaptionMenu( model()->displayName(), this ); - - // This condition is here just as a safety check, fxLineLcdSpinBox is aways - // created inside a TabWidget inside an InstrumentTrackWindow - if ( InstrumentTrackWindow* window = dynamic_cast( (QWidget *)this->parent()->parent() ) ) - { - QMenu *fxMenu = window->instrumentTrackView()->createFxMenu( tr( "Assign to:" ), tr( "New FX channel" ) ); - contextMenu->addMenu( fxMenu ); - - contextMenu->addSeparator(); - } - addDefaultActions( contextMenu ); - contextMenu->exec( QCursor::pos() ); - } - -}; - - - // #### ITW: InstrumentTrackWindow::InstrumentTrackWindow( InstrumentTrackView * _itv ) : QWidget(), @@ -1383,7 +1370,7 @@ InstrumentTrackWindow::InstrumentTrackWindow( InstrumentTrackView * _itv ) : this, SLOT( textChanged( const QString & ) ) ); m_nameLineEdit->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred)); - nameAndChangeTrackLayout->addWidget(m_nameLineEdit); + nameAndChangeTrackLayout->addWidget(m_nameLineEdit, 1); // set up left/right arrows for changing instrument @@ -1468,7 +1455,7 @@ InstrumentTrackWindow::InstrumentTrackWindow( InstrumentTrackView * _itv ) : // setup spinbox for selecting FX-channel - m_effectChannelNumber = new fxLineLcdSpinBox( 2, NULL, tr( "FX channel" ) ); + m_effectChannelNumber = new FxLineLcdSpinBox( 2, NULL, tr( "FX channel" ), m_itv ); basicControlsLayout->addWidget( m_effectChannelNumber, 0, 6 ); basicControlsLayout->setAlignment( m_effectChannelNumber, widgetAlignment ); @@ -1495,8 +1482,11 @@ InstrumentTrackWindow::InstrumentTrackWindow( InstrumentTrackView * _itv ) : generalSettingsLayout->addLayout( basicControlsLayout ); - m_tabWidget = new TabWidget( "", this, true ); - m_tabWidget->setFixedHeight( INSTRUMENT_HEIGHT + GRAPHIC_TAB_HEIGHT - 4 ); + m_tabWidget = new TabWidget( "", this, true, true ); + // "-1" : + // in "TabWidget::addTab", under "Position tab's window", the widget is + // moved up by 1 pixel + m_tabWidget->setMinimumHeight( INSTRUMENT_HEIGHT + GRAPHIC_TAB_HEIGHT - 4 - 1 ); // create tab-widgets @@ -1528,24 +1518,29 @@ InstrumentTrackWindow::InstrumentTrackWindow( InstrumentTrackView * _itv ) : m_tabWidget->addTab( m_effectView, tr( "Effects" ), "fx_tab", 3 ); m_tabWidget->addTab( m_midiView, tr( "MIDI" ), "midi_tab", 4 ); m_tabWidget->addTab( m_miscView, tr( "Miscellaneous" ), "misc_tab", 5 ); + adjustTabSize(m_ssView); + adjustTabSize(instrumentFunctions); + adjustTabSize(m_effectView); + // stupid bugfix, no one knows why + m_effectView->resize(INSTRUMENT_WIDTH - 4, INSTRUMENT_HEIGHT - 4 - 1); + adjustTabSize(m_midiView); + adjustTabSize(m_miscView); // setup piano-widget m_pianoView = new PianoView( this ); - m_pianoView->setFixedSize( INSTRUMENT_WIDTH, PIANO_HEIGHT ); + m_pianoView->setMinimumHeight( PIANO_HEIGHT ); + m_pianoView->setMaximumHeight( PIANO_HEIGHT ); vlayout->addWidget( generalSettingsWidget ); - vlayout->addWidget( m_tabWidget ); + vlayout->addWidget( m_tabWidget, 1 ); vlayout->addWidget( m_pianoView ); - - setModel( _itv->model() ); updateInstrumentView(); - setFixedWidth( INSTRUMENT_WIDTH ); resize( sizeHint() ); - QMdiSubWindow * subWin = gui->mainWindow()->addWindowedWidget( this ); + QMdiSubWindow* subWin = gui->mainWindow()->addWindowedWidget( this ); Qt::WindowFlags flags = subWin->windowFlags(); flags |= Qt::MSWindowsFixedSizeDialogHint; flags &= ~Qt::WindowMaximizeButtonHint; @@ -1558,7 +1553,7 @@ InstrumentTrackWindow::InstrumentTrackWindow( InstrumentTrackView * _itv ) : systemMenu->actions().at( 4 )->setVisible( false ); // Maximize subWin->setWindowIcon( embed::getIconPixmap( "instrument_track" ) ); - subWin->setFixedSize( subWin->size() ); + subWin->setMinimumSize( subWin->size() ); subWin->hide(); } @@ -1589,6 +1584,7 @@ void InstrumentTrackWindow::setInstrumentTrackView( InstrumentTrackView* view ) } m_itv = view; + m_effectChannelNumber->setTrackView(m_itv); } @@ -1669,8 +1665,6 @@ void InstrumentTrackWindow::saveSettingsBtnClicked() !sfd.selectedFiles().isEmpty() && !sfd.selectedFiles().first().isEmpty() ) { - DataFile::LocaleHelper localeHelper( DataFile::LocaleHelper::ModeSave ); - DataFile dataFile( DataFile::InstrumentTrackSettings ); m_track->setSimpleSerializing(); m_track->saveSettings( dataFile, dataFile.content() ); @@ -1710,6 +1704,9 @@ void InstrumentTrackWindow::updateInstrumentView() modelChanged(); // Get the instrument window to refresh m_track->dataChanged(); // Get the text on the trackButton to change + + adjustTabSize(m_instrumentView); + m_pianoView->setVisible(m_track->m_instrument->hasNoteInput()); } } @@ -1764,7 +1761,9 @@ void InstrumentTrackWindow::closeEvent( QCloseEvent* event ) void InstrumentTrackWindow::focusInEvent( QFocusEvent* ) { - m_pianoView->setFocus(); + if(m_pianoView->isVisible()) { + m_pianoView->setFocus(); + } } @@ -1793,7 +1792,7 @@ void InstrumentTrackWindow::dropEvent( QDropEvent* event ) if( type == "instrument" ) { - m_track->loadInstrument( value ); + m_track->loadInstrument( value, nullptr, true /* DnD */ ); Engine::getSong()->setModified(); @@ -1819,7 +1818,9 @@ void InstrumentTrackWindow::dropEvent( QDropEvent* event ) if( !i->descriptor()->supportsFileType( ext ) ) { - i = m_track->loadInstrument( pluginFactory->pluginSupportingExtension(ext).name() ); + PluginFactory::PluginInfoAndKey piakn = + pluginFactory->pluginSupportingExtension(ext); + i = m_track->loadInstrument(piakn.info.name(), &piakn.key); } i->loadFile( value ); @@ -1896,7 +1897,11 @@ void InstrumentTrackWindow::viewInstrumentInDirection(int d) // scroll the SongEditor/BB-editor to make sure the new trackview label is visible bringToFront->trackContainerView()->scrollToTrackView(bringToFront); + + // get the instrument window to refresh + modelChanged(); } + Q_ASSERT(bringToFront); bringToFront->getInstrumentTrackWindow()->setFocus(); } @@ -1909,4 +1914,12 @@ void InstrumentTrackWindow::viewPrevInstrument() viewInstrumentInDirection(-1); } +void InstrumentTrackWindow::adjustTabSize(QWidget *w) +{ + // "-1" : + // in "TabWidget::addTab", under "Position tab's window", the widget is + // moved up by 1 pixel + w->setMinimumSize(INSTRUMENT_WIDTH - 4, INSTRUMENT_HEIGHT - 4 - 1); +} + #include "InstrumentTrack.moc" diff --git a/src/tracks/Pattern.cpp b/src/tracks/Pattern.cpp index 8218d16f6..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(); } @@ -637,6 +637,18 @@ void PatternView::openInPianoRoll() + +void PatternView::setGhostInPianoRoll() +{ + gui->pianoRoll()->setGhostPattern( m_pat ); + gui->pianoRoll()->parentWidget()->show(); + gui->pianoRoll()->show(); + gui->pianoRoll()->setFocus(); +} + + + + void PatternView::resetName() { m_pat->setName( m_pat->m_instrumentTrack->name() ); @@ -663,8 +675,14 @@ void PatternView::constructContextMenu( QMenu * _cm ) _cm->insertAction( _cm->actions()[0], a ); connect( a, SIGNAL( triggered( bool ) ), this, SLOT( openInPianoRoll() ) ); - _cm->insertSeparator( _cm->actions()[1] ); + QAction * b = new QAction( embed::getIconPixmap( "ghost_note" ), + tr( "Set as ghost in piano-roll" ), _cm ); + if( m_pat->empty() ) { b->setEnabled( false ); } + _cm->insertAction( _cm->actions()[1], b ); + connect( b, SIGNAL( triggered( bool ) ), + this, SLOT( setGhostInPianoRoll() ) ); + _cm->insertSeparator( _cm->actions()[2] ); _cm->addSeparator(); _cm->addAction( embed::getIconPixmap( "edit_erase" ), @@ -697,8 +715,7 @@ void PatternView::mousePressEvent( QMouseEvent * _me ) { if( _me->button() == Qt::LeftButton && m_pat->m_patternType == Pattern::BeatPattern && - ( fixedTCOs() || pixelsPerTact() >= 96 || - m_pat->m_steps != MidiTime::stepsPerTact() ) && + ( fixedTCOs() || pixelsPerBar() >= 96 ) && _me->y() > height() - s_stepBtnOff->height() ) // when mouse button is pressed in beat/bassline -mode @@ -768,8 +785,7 @@ void PatternView::mouseDoubleClickEvent(QMouseEvent *_me) void PatternView::wheelEvent( QWheelEvent * _we ) { if( m_pat->m_patternType == Pattern::BeatPattern && - ( fixedTCOs() || pixelsPerTact() >= 96 || - m_pat->m_steps != MidiTime::stepsPerTact() ) && + ( fixedTCOs() || pixelsPerBar() >= 96 ) && _we->y() > height() - s_stepBtnOff->height() ) { // get the step number that was wheeled on and @@ -886,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; @@ -1013,8 +1029,7 @@ void PatternView::paintEvent( QPaintEvent * ) } // beat pattern paint event - else if( beatPattern && ( fixedTCOs() || pixelsPerTact >= 96 - || m_pat->m_steps != MidiTime::stepsPerTact() ) ) + else if( beatPattern && ( fixedTCOs() || pixelsPerBar >= 96 ) ) { QPixmap stepon0; QPixmap stepon200; @@ -1082,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 3315ccb55..72f63bb05 100644 --- a/src/tracks/SampleTrack.cpp +++ b/src/tracks/SampleTrack.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -48,6 +49,8 @@ #include "MainWindow.h" #include "Mixer.h" #include "EffectRackView.h" +#include "FxMixerView.h" +#include "TabWidget.h" #include "TrackLabelButton.h" SampleTCO::SampleTCO( Track * _track ) : @@ -62,7 +65,7 @@ SampleTCO::SampleTCO( Track * _track ) : // we need to receive bpm-change-events, because then we have to // change length of this TCO connect( Engine::getSong(), SIGNAL( tempoChanged( bpm_t ) ), - this, SLOT( updateLength() ) ); + this, SLOT( updateLength() ), Qt::DirectConnection ); connect( Engine::getSong(), SIGNAL( timeSignatureChanged( int,int ) ), this, SLOT( updateLength() ) ); @@ -73,13 +76,16 @@ SampleTCO::SampleTCO( Track * _track ) : connect( timeLine, SIGNAL( positionMarkerMoved() ), this, SLOT( playbackPositionChanged() ) ); } //playbutton clicked or space key / on Export Song set isPlaying to false - connect( Engine::getSong(), SIGNAL( playbackStateChanged() ), this, SLOT( playbackPositionChanged() ) ); + connect( Engine::getSong(), SIGNAL( playbackStateChanged() ), + this, SLOT( playbackPositionChanged() ), Qt::DirectConnection ); //care about loops - connect( Engine::getSong(), SIGNAL( updateSampleTracks() ), this, SLOT( playbackPositionChanged() ) ); + connect( Engine::getSong(), SIGNAL( updateSampleTracks() ), + this, SLOT( playbackPositionChanged() ), Qt::DirectConnection ); //care about mute TCOs connect( this, SIGNAL( dataChanged() ), this, SLOT( playbackPositionChanged() ) ); //care about mute track - connect( getTrack()->getMutedModel(), SIGNAL( dataChanged() ),this, SLOT( playbackPositionChanged() ) ); + connect( getTrack()->getMutedModel(), SIGNAL( dataChanged() ), + this, SLOT( playbackPositionChanged() ), Qt::DirectConnection ); //care about TCO position connect( this, SIGNAL( positionChanged() ), this, SLOT( updateTrackTcos() ) ); @@ -104,11 +110,13 @@ SampleTCO::SampleTCO( Track * _track ) : SampleTCO::~SampleTCO() { SampleTrack * sampletrack = dynamic_cast( getTrack() ); - if( sampletrack) + if ( sampletrack ) { sampletrack->updateTcos(); } + Engine::mixer()->requestChangeInModel(); sharedObject::unref( m_sampleBuffer ); + Engine::mixer()->doneChangeInModel(); } @@ -116,10 +124,7 @@ SampleTCO::~SampleTCO() void SampleTCO::changeLength( const MidiTime & _length ) { - float nom = Engine::getSong()->getTimeSigModel().getNumerator(); - float den = Engine::getSong()->getTimeSigModel().getDenominator(); - int ticksPerTact = DefaultTicksPerTact * ( nom / den ); - TrackContentObject::changeLength( qMax( static_cast( _length ), ticksPerTact ) ); + TrackContentObject::changeLength( qMax( static_cast( _length ), 1 ) ); } @@ -134,7 +139,9 @@ const QString & SampleTCO::sampleFile() const void SampleTCO::setSampleBuffer( SampleBuffer* sb ) { + Engine::mixer()->requestChangeInModel(); sharedObject::unref( m_sampleBuffer ); + Engine::mixer()->doneChangeInModel(); m_sampleBuffer = sb; updateLength(); @@ -145,9 +152,21 @@ void SampleTCO::setSampleBuffer( SampleBuffer* sb ) void SampleTCO::setSampleFile( const QString & _sf ) { - m_sampleBuffer->setAudioFile( _sf ); + int length; + if ( _sf.isEmpty() ) + { //When creating an empty sample pattern make it a bar long + float nom = Engine::getSong()->getTimeSigModel().getNumerator(); + float den = Engine::getSong()->getTimeSigModel().getDenominator(); + length = DefaultTicksPerBar * ( nom / den ); + } + else + { //Otherwise set it to the sample's length + m_sampleBuffer->setAudioFile( _sf ); + length = sampleLength(); + } + changeLength(length); + setStartTimeOffset( 0 ); - changeLength( (int) ( m_sampleBuffer->frames() / Engine::framesPerTick() ) ); emit sampleChanged(); emit playbackPositionChanged(); @@ -254,6 +273,8 @@ void SampleTCO::saveSettings( QDomDocument & _doc, QDomElement & _this ) QString s; _this.setAttribute( "data", m_sampleBuffer->toBase64( s ) ); } + + _this.setAttribute ("sample_rate", m_sampleBuffer->sampleRate()); // TODO: start- and end-frame } @@ -274,6 +295,10 @@ void SampleTCO::loadSettings( const QDomElement & _this ) changeLength( _this.attribute( "len" ).toInt() ); setMuted( _this.attribute( "muted" ).toInt() ); setStartTimeOffset( _this.attribute( "off" ).toInt() ); + + if (_this.hasAttribute("sample_rate")) { + m_sampleBuffer->setSampleRate(_this.attribute("sample_rate").toInt()); + } } @@ -338,12 +363,7 @@ void SampleTCOView::contextMenuEvent( QContextMenuEvent * _cme ) tr( "Paste" ), m_tco, SLOT( paste() ) ); contextMenu.addSeparator(); contextMenu.addAction( embed::getIconPixmap( "muted" ), - tr( "Mute/unmute (<%1> + middle click)" ).arg( - #ifdef LMMS_BUILD_APPLE - "⌘"), - #else - "Ctrl"), - #endif + tr( "Mute/unmute (<%1> + middle click)" ).arg(UI_CTRL_KEY), m_tco, SLOT( toggleMute() ) ); /*contextMenu.addAction( embed::getIconPixmap( "record" ), tr( "Set/clear record" ), @@ -439,8 +459,15 @@ void SampleTCOView::mouseReleaseEvent(QMouseEvent *_me) void SampleTCOView::mouseDoubleClickEvent( QMouseEvent * ) { QString af = m_tco->m_sampleBuffer->openAudioFile(); - if( af != "" && af != m_tco->m_sampleBuffer->audioFile() ) - { + + if ( af.isEmpty() ) {} //Don't do anything if no file is loaded + else if ( af == m_tco->m_sampleBuffer->audioFile() ) + { //Instead of reloading the existing file, just reset the size + int length = (int) ( m_tco->m_sampleBuffer->frames() / Engine::framesPerTick() ); + m_tco->changeLength(length); + } + else + { //Otherwise load the new file as ususal m_tco->setSampleFile( af ); Engine::getSong()->setModified(); } @@ -473,7 +500,7 @@ void SampleTCOView::paintEvent( QPaintEvent * pe ) bool muted = m_tco->getTrack()->isMuted() || m_tco->isMuted(); // state: selected, muted, normal - c = isSelected() ? selectedColor() : ( muted ? mutedBackgroundColor() + c = isSelected() ? selectedColor() : ( muted ? mutedBackgroundColor() : painter.background().color() ); lingrad.setColorAt( 1, c.darker( 300 ) ); @@ -494,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 offset = m_tco->startTimeOffset() / ticksPerTact * pixelsPerTact(); + float ticksPerBar = DefaultTicksPerBar * nom / den; + + 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()); @@ -517,7 +544,7 @@ void SampleTCOView::paintEvent( QPaintEvent * pe ) // inner border p.setPen( c.lighter( 160 ) ); - p.drawRect( 1, 1, rect().right() - TCO_BORDER_WIDTH, + p.drawRect( 1, 1, rect().right() - TCO_BORDER_WIDTH, rect().bottom() - TCO_BORDER_WIDTH ); // outer border @@ -533,7 +560,7 @@ void SampleTCOView::paintEvent( QPaintEvent * pe ) embed::getIconPixmap( "muted", size, size ) ); } - // recording sample tracks is not possible at the moment + // recording sample tracks is not possible at the moment /* if( m_tco->isRecord() ) { @@ -564,10 +591,14 @@ SampleTrack::SampleTrack( TrackContainer* tc ) : tr( "Volume" ) ), m_panningModel( DefaultPanning, PanningLeft, PanningRight, 0.1f, this, tr( "Panning" ) ), + m_effectChannelModel( 0, 0, 0, this, tr( "FX channel" ) ), m_audioPort( tr( "Sample track" ), true, &m_volumeModel, &m_panningModel, &m_mutedModel ) { setName( tr( "Sample track" ) ); m_panningModel.setCenterValue( DefaultPanning ); + m_effectChannelModel.setRange( 0, Engine::fxMixer()->numChannels()-1, 1); + + connect( &m_effectChannelModel, SIGNAL( dataChanged() ), this, SLOT( updateEffectChannel() ) ); } @@ -607,13 +638,14 @@ bool SampleTrack::play( const MidiTime & _start, const fpp_t _frames, { TrackContentObject * tco = getTCO( i ); SampleTCO * sTco = dynamic_cast( tco ); - float framesPerTick = Engine::framesPerTick(); + if( _start >= sTco->startPosition() && _start < sTco->endPosition() ) { if( sTco->isPlaying() == false && _start > sTco->startPosition() + sTco->startTimeOffset() ) { - f_cnt_t sampleStart = framesPerTick * ( _start - sTco->startPosition() - sTco->startTimeOffset() ); - f_cnt_t tcoFrameLength = framesPerTick * ( sTco->endPosition() - sTco->startPosition() - sTco->startTimeOffset() ); + auto bufferFramesPerTick = Engine::framesPerTick (sTco->sampleBuffer ()->sampleRate ()); + f_cnt_t sampleStart = bufferFramesPerTick * ( _start - sTco->startPosition() - sTco->startTimeOffset() ); + f_cnt_t tcoFrameLength = bufferFramesPerTick * ( sTco->endPosition() - sTco->startPosition() - sTco->startTimeOffset() ); f_cnt_t sampleBufferLength = sTco->sampleBuffer()->frames(); //if the Tco smaller than the sample length we play only until Tco end //else we play the sample to the end but nothing more @@ -678,9 +710,11 @@ TrackView * SampleTrack::createView( TrackContainerView* tcv ) -TrackContentObject * SampleTrack::createTCO( const MidiTime & ) +TrackContentObject * SampleTrack::createTCO(const MidiTime & pos) { - return new SampleTCO( this ); + SampleTCO * sTco = new SampleTCO(this); + sTco->movePosition(pos); + return sTco; } @@ -695,6 +729,7 @@ void SampleTrack::saveTrackSpecificSettings( QDomDocument & _doc, #endif m_volumeModel.saveSettings( _doc, _this, "vol" ); m_panningModel.saveSettings( _doc, _this, "pan" ); + m_effectChannelModel.saveSettings( _doc, _this, "fxch" ); } @@ -717,6 +752,8 @@ void SampleTrack::loadTrackSpecificSettings( const QDomElement & _this ) } m_volumeModel.loadSettings( _this, "vol" ); m_panningModel.loadSettings( _this, "pan" ); + m_effectChannelModel.setRange( 0, Engine::fxMixer()->numChannels() - 1 ); + m_effectChannelModel.loadSettings( _this, "fxch" ); } @@ -744,6 +781,14 @@ void SampleTrack::setPlayingTcos( bool isPlaying ) +void SampleTrack::updateEffectChannel() +{ + m_audioPort.setNextFxChannel( m_effectChannelModel.value() ); +} + + + + SampleTrackView::SampleTrackView( SampleTrack * _t, TrackContainerView* tcv ) : @@ -751,28 +796,25 @@ SampleTrackView::SampleTrackView( SampleTrack * _t, TrackContainerView* tcv ) : { setFixedHeight( 32 ); - TrackLabelButton * tlb = new TrackLabelButton( this, - getTrackSettingsWidget() ); - connect( tlb, SIGNAL( clicked( bool ) ), - this, SLOT( showEffects() ) ); - tlb->setIcon( embed::getIconPixmap( "sample_track" ) ); - tlb->move( 3, 1 ); - tlb->show(); + m_tlb = new TrackLabelButton(this, getTrackSettingsWidget()); + m_tlb->setCheckable(true); + connect(m_tlb, SIGNAL(clicked( bool )), + this, SLOT(showEffects())); + m_tlb->setIcon(embed::getIconPixmap("sample_track")); + m_tlb->move(3, 1); + m_tlb->show(); m_volumeKnob = new Knob( knobSmall_17, getTrackSettingsWidget(), tr( "Track volume" ) ); m_volumeKnob->setVolumeKnob( true ); m_volumeKnob->setModel( &_t->m_volumeModel ); m_volumeKnob->setHintText( tr( "Channel volume:" ), "%" ); - if( ConfigManager::inst()->value( "ui", - "compacttrackbuttons" ).toInt() ) - { - m_volumeKnob->move( DEFAULT_SETTINGS_WIDGET_WIDTH_COMPACT-2*24, 2 ); - } - else - { - m_volumeKnob->move( DEFAULT_SETTINGS_WIDGET_WIDTH-2*24, 2 ); - } + + int settingsWidgetWidth = ConfigManager::inst()-> + value( "ui", "compacttrackbuttons" ).toInt() + ? DEFAULT_SETTINGS_WIDGET_WIDTH_COMPACT + : DEFAULT_SETTINGS_WIDGET_WIDTH; + m_volumeKnob->move( settingsWidgetWidth - 2 * 24, 2 ); m_volumeKnob->setLabel( tr( "VOL" ) ); m_volumeKnob->show(); @@ -780,20 +822,14 @@ SampleTrackView::SampleTrackView( SampleTrack * _t, TrackContainerView* tcv ) : tr( "Panning" ) ); m_panningKnob->setModel( &_t->m_panningModel ); m_panningKnob->setHintText( tr( "Panning:" ), "%" ); - m_panningKnob->move( DEFAULT_SETTINGS_WIDGET_WIDTH-24, 2 ); + m_panningKnob->move( settingsWidgetWidth - 24, 2 ); m_panningKnob->setLabel( tr( "PAN" ) ); m_panningKnob->show(); - m_effectRack = new EffectRackView( _t->audioPort()->effects() ); - m_effectRack->setFixedSize( 240, 242 ); - - m_effWindow = gui->mainWindow()->addWindowedWidget( m_effectRack ); - m_effWindow->setAttribute( Qt::WA_DeleteOnClose, false ); - m_effWindow->layout()->setSizeConstraint( QLayout::SetFixedSize ); - m_effWindow->setWindowTitle( _t->name() ); - m_effWindow->hide(); - setModel( _t ); + + m_window = new SampleTrackWindow(this); + m_window->toggleVisibility(false); } @@ -801,7 +837,49 @@ SampleTrackView::SampleTrackView( SampleTrack * _t, TrackContainerView* tcv ) : SampleTrackView::~SampleTrackView() { - m_effWindow->deleteLater(); + if(m_window != NULL) + { + m_window->setSampleTrackView(NULL); + m_window->parentWidget()->hide(); + } + m_window = NULL; +} + + + +//FIXME: This is identical to InstrumentTrackView::createFxMenu +QMenu * SampleTrackView::createFxMenu(QString title, QString newFxLabel) +{ + int channelIndex = model()->effectChannelModel()->value(); + + FxChannel *fxChannel = Engine::fxMixer()->effectChannel(channelIndex); + + // If title allows interpolation, pass channel index and name + if (title.contains("%2")) + { + title = title.arg(channelIndex).arg(fxChannel->m_name); + } + + QMenu *fxMenu = new QMenu(title); + + fxMenu->addAction(newFxLabel, this, SLOT(createFxLine())); + fxMenu->addSeparator(); + + for (int i = 0; i < Engine::fxMixer()->numChannels(); ++i) + { + FxChannel * currentChannel = Engine::fxMixer()->effectChannel(i); + + if (currentChannel != fxChannel) + { + const auto index = currentChannel->m_channelIndex; + QString label = tr("FX %1: %2").arg(currentChannel->m_channelIndex).arg(currentChannel->m_name); + fxMenu->addAction(label, [this, index](){ + assignFxLine(index); + }); + } + } + + return fxMenu; } @@ -809,16 +887,7 @@ SampleTrackView::~SampleTrackView() void SampleTrackView::showEffects() { - if( m_effWindow->isHidden() ) - { - m_effectRack->show(); - m_effWindow->show(); - m_effWindow->raise(); - } - else - { - m_effWindow->hide(); - } + m_window->toggleVisibility(m_window->parentWidget()->isHidden()); } @@ -826,7 +895,299 @@ void SampleTrackView::showEffects() void SampleTrackView::modelChanged() { SampleTrack * st = castModel(); - m_volumeKnob->setModel( &st->m_volumeModel ); + m_volumeKnob->setModel(&st->m_volumeModel); TrackView::modelChanged(); } + + + + +void SampleTrackView::dragEnterEvent(QDragEnterEvent *dee) +{ + StringPairDrag::processDragEnterEvent(dee, QString("samplefile")); +} + + + + +void SampleTrackView::dropEvent(QDropEvent *de) +{ + QString type = StringPairDrag::decodeKey(de); + QString value = StringPairDrag::decodeValue(de); + + if (type == "samplefile") + { + int trackHeadWidth = ConfigManager::inst()->value("ui", "compacttrackbuttons").toInt()==1 + ? DEFAULT_SETTINGS_WIDGET_WIDTH_COMPACT + TRACK_OP_WIDTH_COMPACT + : DEFAULT_SETTINGS_WIDGET_WIDTH + TRACK_OP_WIDTH; + + int xPos = de->pos().x() < trackHeadWidth + ? trackHeadWidth + : de->pos().x(); + + MidiTime tcoPos = trackContainerView()->fixedTCOs() + ? MidiTime(0) + : MidiTime(((xPos - trackHeadWidth) / trackContainerView()->pixelsPerBar() + * MidiTime::ticksPerBar()) + trackContainerView()->currentPosition() + ).quantize(1.0); + + SampleTCO * sTco = static_cast(getTrack()->createTCO(tcoPos)); + if (sTco) { sTco->setSampleFile(value); } + } + +} + + + + +SampleTrackWindow::SampleTrackWindow(SampleTrackView * tv) : + QWidget(), + ModelView(NULL, this), + m_track(tv->model()), + m_stv(tv) +{ + // init own layout + widgets + setFocusPolicy(Qt::StrongFocus); + QVBoxLayout * vlayout = new QVBoxLayout(this); + vlayout->setMargin(0); + vlayout->setSpacing(0); + + TabWidget* generalSettingsWidget = new TabWidget(tr("GENERAL SETTINGS"), this); + + QVBoxLayout* generalSettingsLayout = new QVBoxLayout(generalSettingsWidget); + + generalSettingsLayout->setContentsMargins(8, 18, 8, 8); + generalSettingsLayout->setSpacing(6); + + QWidget* nameWidget = new QWidget(generalSettingsWidget); + QHBoxLayout* nameLayout = new QHBoxLayout(nameWidget); + nameLayout->setContentsMargins(0, 0, 0, 0); + nameLayout->setSpacing(2); + + // setup line edit for changing sample track name + m_nameLineEdit = new QLineEdit; + m_nameLineEdit->setFont(pointSize<9>(m_nameLineEdit->font())); + connect(m_nameLineEdit, SIGNAL(textChanged(const QString &)), + this, SLOT(textChanged(const QString &))); + + m_nameLineEdit->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred)); + nameLayout->addWidget(m_nameLineEdit); + + + generalSettingsLayout->addWidget(nameWidget); + + + QGridLayout* basicControlsLayout = new QGridLayout; + basicControlsLayout->setHorizontalSpacing(3); + basicControlsLayout->setVerticalSpacing(0); + basicControlsLayout->setContentsMargins(0, 0, 0, 0); + + QString labelStyleSheet = "font-size: 6pt;"; + Qt::Alignment labelAlignment = Qt::AlignHCenter | Qt::AlignTop; + Qt::Alignment widgetAlignment = Qt::AlignHCenter | Qt::AlignCenter; + + // set up volume knob + m_volumeKnob = new Knob(knobBright_26, NULL, tr("Sample volume")); + m_volumeKnob->setVolumeKnob(true); + m_volumeKnob->setHintText(tr("Volume:"), "%"); + + basicControlsLayout->addWidget(m_volumeKnob, 0, 0); + basicControlsLayout->setAlignment(m_volumeKnob, widgetAlignment); + + QLabel *label = new QLabel(tr("VOL"), this); + label->setStyleSheet(labelStyleSheet); + basicControlsLayout->addWidget(label, 1, 0); + basicControlsLayout->setAlignment(label, labelAlignment); + + + // set up panning knob + m_panningKnob = new Knob(knobBright_26, NULL, tr("Panning")); + m_panningKnob->setHintText(tr("Panning:"), ""); + + basicControlsLayout->addWidget(m_panningKnob, 0, 1); + basicControlsLayout->setAlignment(m_panningKnob, widgetAlignment); + + label = new QLabel(tr("PAN"),this); + label->setStyleSheet(labelStyleSheet); + basicControlsLayout->addWidget(label, 1, 1); + basicControlsLayout->setAlignment(label, labelAlignment); + + + basicControlsLayout->setColumnStretch(2, 1); + + + // setup spinbox for selecting FX-channel + m_effectChannelNumber = new FxLineLcdSpinBox(2, NULL, tr("FX channel"), m_stv); + + basicControlsLayout->addWidget(m_effectChannelNumber, 0, 3); + basicControlsLayout->setAlignment(m_effectChannelNumber, widgetAlignment); + + label = new QLabel(tr("FX"), this); + label->setStyleSheet(labelStyleSheet); + basicControlsLayout->addWidget(label, 1, 3); + basicControlsLayout->setAlignment(label, labelAlignment); + + generalSettingsLayout->addLayout(basicControlsLayout); + + m_effectRack = new EffectRackView(tv->model()->audioPort()->effects()); + m_effectRack->setFixedSize(240, 242); + + vlayout->addWidget(generalSettingsWidget); + vlayout->addWidget(m_effectRack); + + + setModel(tv->model()); + + QMdiSubWindow * subWin = gui->mainWindow()->addWindowedWidget(this); + Qt::WindowFlags flags = subWin->windowFlags(); + flags |= Qt::MSWindowsFixedSizeDialogHint; + flags &= ~Qt::WindowMaximizeButtonHint; + subWin->setWindowFlags(flags); + + // Hide the Size and Maximize options from the system menu + // since the dialog size is fixed. + QMenu * systemMenu = subWin->systemMenu(); + systemMenu->actions().at(2)->setVisible(false); // Size + systemMenu->actions().at(4)->setVisible(false); // Maximize + + subWin->setWindowIcon(embed::getIconPixmap("sample_track")); + subWin->setFixedSize(subWin->size()); + subWin->hide(); +} + + + +SampleTrackWindow::~SampleTrackWindow() +{ +} + + + +void SampleTrackWindow::setSampleTrackView(SampleTrackView* tv) +{ + if(m_stv && tv) + { + m_stv->m_tlb->setChecked(false); + } + + m_stv = tv; +} + + + +void SampleTrackWindow::modelChanged() +{ + m_track = castModel(); + + m_nameLineEdit->setText(m_track->name()); + + m_track->disconnect(SIGNAL(nameChanged()), this); + + connect(m_track, SIGNAL(nameChanged()), + this, SLOT(updateName())); + + m_volumeKnob->setModel(&m_track->m_volumeModel); + m_panningKnob->setModel(&m_track->m_panningModel); + m_effectChannelNumber->setModel(&m_track->m_effectChannelModel); + + updateName(); +} + + + +/*! \brief Create and assign a new FX Channel for this track */ +void SampleTrackView::createFxLine() +{ + int channelIndex = gui->fxMixerView()->addNewChannel(); + + Engine::fxMixer()->effectChannel(channelIndex)->m_name = getTrack()->name(); + + assignFxLine(channelIndex); +} + + + + +/*! \brief Assign a specific FX Channel for this track */ +void SampleTrackView::assignFxLine(int channelIndex) +{ + model()->effectChannelModel()->setValue(channelIndex); + + gui->fxMixerView()->setCurrentFxLine(channelIndex); +} + + + +void SampleTrackWindow::updateName() +{ + setWindowTitle(m_track->name().length() > 25 ? (m_track->name().left(24) + "...") : m_track->name()); + + if(m_nameLineEdit->text() != m_track->name()) + { + m_nameLineEdit->setText(m_track->name()); + } +} + + + +void SampleTrackWindow::textChanged(const QString& new_name) +{ + m_track->setName(new_name); + Engine::getSong()->setModified(); +} + + + +void SampleTrackWindow::toggleVisibility(bool on) +{ + if(on) + { + show(); + parentWidget()->show(); + parentWidget()->raise(); + } + else + { + parentWidget()->hide(); + } +} + + + + +void SampleTrackWindow::closeEvent(QCloseEvent* ce) +{ + ce->ignore(); + + if(gui->mainWindow()->workspace()) + { + parentWidget()->hide(); + } + else + { + hide(); + } + + m_stv->m_tlb->setFocus(); + m_stv->m_tlb->setChecked(false); +} + + + +void SampleTrackWindow::saveSettings(QDomDocument& doc, QDomElement & element) +{ + MainWindow::saveWidgetState(this, element); + Q_UNUSED(element) +} + + + +void SampleTrackWindow::loadSettings(const QDomElement& element) +{ + MainWindow::restoreWidgetState(this, element); + if(isVisible()) + { + m_stv->m_tlb->setChecked(true); + } +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index ca78a5eb4..ddebe116c 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -2,6 +2,7 @@ INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}") INCLUDE_DIRECTORIES("${CMAKE_CURRENT_BINARY_DIR}") INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/include") INCLUDE_DIRECTORIES("${CMAKE_BINARY_DIR}") +INCLUDE_DIRECTORIES("${CMAKE_BINARY_DIR}/src") SET(CMAKE_CXX_STANDARD 11) @@ -13,10 +14,14 @@ ADD_EXECUTABLE(tests QTestSuite $ + src/core/AutomatableModelTest.cpp src/core/ProjectVersionTest.cpp src/core/RelativePathsTest.cpp src/tracks/AutomationTrackTest.cpp ) +TARGET_COMPILE_DEFINITIONS(tests + PRIVATE $ +) TARGET_LINK_LIBRARIES(tests ${QT_LIBRARIES} ${QT_QTTEST_LIBRARY}) TARGET_LINK_LIBRARIES(tests ${LMMS_REQUIRED_LIBS}) diff --git a/tests/src/core/AutomatableModelTest.cpp b/tests/src/core/AutomatableModelTest.cpp new file mode 100644 index 000000000..116f95e60 --- /dev/null +++ b/tests/src/core/AutomatableModelTest.cpp @@ -0,0 +1,55 @@ +/* + * AutomatableModelTest.cpp + * + * Copyright (c) 2019-2019 Johannes Lorenz + * + * 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. + * + */ + +#include "QTestSuite.h" + +#include "AutomatableModel.h" +#include "ComboBoxModel.h" + +class AutomatableModelTest : QTestSuite +{ + Q_OBJECT + +private slots: + //! Test that upcast and exact casts work, + //! but no downcast or any other casts + void CastTests() + { + ComboBoxModel comboModel; + AutomatableModel* amPtr = &comboModel; + QVERIFY(nullptr == amPtr->dynamicCast()); // not a parent class + QCOMPARE(&comboModel, amPtr->dynamicCast()); // parent class + QCOMPARE(&comboModel, amPtr->dynamicCast()); // parent class + QCOMPARE(&comboModel, amPtr->dynamicCast()); // same class + + IntModel intModel; + IntModel* imPtr = &intModel; + QVERIFY(nullptr == imPtr->dynamicCast()); // not a parent class + QCOMPARE(&intModel, imPtr->dynamicCast()); // parent class + QCOMPARE(&intModel, imPtr->dynamicCast()); // same class + QVERIFY(nullptr == imPtr->dynamicCast()); // child class + } +} AutomatableModelTests; + +#include "AutomatableModelTest.moc" diff --git a/tests/src/tracks/AutomationTrackTest.cpp b/tests/src/tracks/AutomationTrackTest.cpp index 65c3b4874..291ae293e 100644 --- a/tests/src/tracks/AutomationTrackTest.cpp +++ b/tests/src/tracks/AutomationTrackTest.cpp @@ -186,13 +186,37 @@ 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() + { + // Global automation should not have priority, see https://github.com/LMMS/lmms/issues/4268 + // Tests regression caused by 75077f6200a5aee3a5821aae48a3b8466ed8714a + auto song = Engine::getSong(); + + auto globalTrack = song->globalAutomationTrack(); + AutomationPattern globalPattern(globalTrack); + + AutomationTrack localTrack(song); + AutomationPattern localPattern(&localTrack); + + FloatModel model; + globalPattern.setProgressionType(AutomationPattern::DiscreteProgression); + localPattern.setProgressionType(AutomationPattern::DiscreteProgression); + globalPattern.addObject(&model); + localPattern.addObject(&model); + globalPattern.putValue(0, 100.0f, false); + localPattern.putValue(0, 50.0f, false); + + QCOMPARE(song->automatedValuesAt(0)[&model], 50.0f); + } + } AutomationTrackTest; #include "AutomationTrackTest.moc"