diff --git a/.travis.yml b/.travis.yml index 390f7f0b6..24c6df1c9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,7 @@ before_script: - mkdir build && cd build script: - sh ${TRAVIS_BUILD_DIR}/.travis/${TRAVIS_OS_NAME}.${TARGET_OS}.script.sh - - make -j4 VERBOSE=1 + - make -j4 - if [[ $TARGET_OS != win* ]]; then make tests && ./tests/tests; fi; before_deploy: make package deploy: diff --git a/CMakeLists.txt b/CMakeLists.txt index a526df3df..1ba886503 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -575,8 +575,8 @@ IF(WIN32) SET(CPACK_NSIS_MUI_ICON "${CMAKE_SOURCE_DIR}/data/lmms.ico") SET(CPACK_NSIS_INSTALLED_ICON_NAME "lmms.exe") SET(CPACK_NSIS_DISPLAY_NAME "LMMS ${VERSION}") - SET(CPACK_NSIS_HELP_LINK "http:\\\\\\\\lmms.io") - SET(CPACK_NSIS_URL_INFO_ABOUT "http:\\\\\\\\lmms.io") + SET(CPACK_NSIS_HELP_LINK "http://lmms.io") + SET(CPACK_NSIS_URL_INFO_ABOUT "http://lmms.io") SET(CPACK_NSIS_CONTACT "lmms-devel@lists.sourceforge.net") SET(CPACK_PACKAGE_EXECUTABLES "lmms.exe;LMMS") SET(CPACK_NSIS_MENU_LINKS "lmms.exe;LMMS") diff --git a/cmake/modules/DetectMachine.cmake b/cmake/modules/DetectMachine.cmake index ccb8638be..5bbbef44e 100644 --- a/cmake/modules/DetectMachine.cmake +++ b/cmake/modules/DetectMachine.cmake @@ -1,11 +1,11 @@ IF(WIN32) SET(LMMS_BUILD_WIN32 1) -ELSE(WIN32) - IF(APPLE) - SET(LMMS_BUILD_APPLE 1) - ELSE(APPLE) - SET(LMMS_BUILD_LINUX 1) - ENDIF(APPLE) +ELSEIF(APPLE) + SET(LMMS_BUILD_APPLE 1) +ELSEIF(HAIKU) + SET(LMMS_BUILD_HAIKU 1) +ELSE() + SET(LMMS_BUILD_LINUX 1) ENDIF(WIN32) MESSAGE("PROCESSOR: ${CMAKE_SYSTEM_PROCESSOR}") diff --git a/data/locale/ca.ts b/data/locale/ca.ts index f59930462..edc368108 100644 --- a/data/locale/ca.ts +++ b/data/locale/ca.ts @@ -3556,6 +3556,14 @@ Per favor, visita http://lmms.sf.net/wiki per a documentació sobre LMMS.LMMS Project (*.mmpz *.mmp);;LMMS Project Template (*.mpt) + + LMMS Project + + + + LMMS Project Template + + My Projects @@ -6147,8 +6155,8 @@ Per favor, assegura't que tens permís de lectura per al fitxer i el direct semitons - With this knob you can set the coarse detuning of oscillator %1. You can detune the oscillator 12 semitones (1 octave) up and down. This is useful for creating sounds with a chord. - Amb aquesta roda pots ajustar el desafinament gruixut de l'oscil·lador %1. Pots desafinar l'oscil·lador 12 semitons (1 octava) cap a dalt i a baix. Això és útil per a crear sons amb un acord. + 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. + Amb aquesta roda pots ajustar el desafinament gruixut de l'oscil·lador %1. Pots desafinar l'oscil·lador 24 semitons (1 octavaes) cap a dalt i a baix. Això és útil per a crear sons amb un acord. Osc %1 fine detuning left: @@ -8521,7 +8529,7 @@ This chip was used in the Commodore 64 computer. - PulseAudio (bad latency!) + PulseAudio diff --git a/data/locale/cs.ts b/data/locale/cs.ts index 12bc754bb..b0381f897 100644 --- a/data/locale/cs.ts +++ b/data/locale/cs.ts @@ -3556,6 +3556,14 @@ Navštivte prosím stránku s dokumentací k LMMS na adrese http://lmms.sf.net/w LMMS Project (*.mmpz *.mmp);;LMMS Project Template (*.mpt) + + LMMS Project + + + + LMMS Project Template + + My Projects @@ -6149,7 +6157,7 @@ Přesvědčte se prosím, že máte právo ke čtení tohoto souboru a příslu - With this knob you can set the coarse detuning of oscillator %1. You can detune the oscillator 12 semitones (1 octave) up and down. This is useful for creating sounds with a chord. + 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. @@ -8523,7 +8531,7 @@ This chip was used in the Commodore 64 computer. - PulseAudio (bad latency!) + PulseAudio diff --git a/data/locale/de.ts b/data/locale/de.ts index f6f4194cd..090e2bc79 100644 --- a/data/locale/de.ts +++ b/data/locale/de.ts @@ -3573,6 +3573,14 @@ Bitte besuchen Sie http://lmms.sf.net/wiki für Dokumentationen über LMMS.LMMS Project (*.mmpz *.mmp);;LMMS Project Template (*.mpt) LMMS Projekt (*.mmpz *.mmp);;LMMS Projektvorlage (*.mpt) + + LMMS Project + LMMS Projekt + + + LMMS Project Template + LMMS Projektvorlage + Volumes Volumes @@ -6185,8 +6193,8 @@ Bitte stellen Sie sicher, dass Sie Leserechte auf diese Datei sowie das Verzeich Halbtöne - With this knob you can set the coarse detuning of oscillator %1. You can detune the oscillator 12 semitones (1 octave) up and down. This is useful for creating sounds with a chord. - Mit diesem Regler können Sie die grobe Verstimmung von Oszillator %1 setzen. Sie können den Oszillator 12 Halbtöne (1 Oktave) nach oben und unten verstimmen. Das ist nützlich, wenn Sie einen Sound mit einem Akkord erstellen möchten. + 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. + Mit diesem Regler können Sie die grobe Verstimmung von Oszillator %1 setzen. Sie können den Oszillator 24 Halbtöne (2 Oktaven) nach oben und unten verstimmen. Das ist nützlich, wenn Sie einen Sound mit einem Akkord erstellen möchten. Osc %1 fine detuning left: @@ -8568,7 +8576,7 @@ Dieser Chip wurde in Commodore 64 Computern genutzt. ALSA Raw-MIDI (Advanced Linux Sound Architecture) - PulseAudio (bad latency!) + PulseAudio PulseAudio (Schlechte Latenz!) diff --git a/data/locale/en.ts b/data/locale/en.ts index 49f9dcbd3..0c4bae00b 100644 --- a/data/locale/en.ts +++ b/data/locale/en.ts @@ -3550,7 +3550,11 @@ Please visit http://lmms.sf.net/wiki for documentation on LMMS. - LMMS Project (*.mmpz *.mmp);;LMMS Project Template (*.mpt) + LMMS Project + + + + LMMS Project Template @@ -6140,7 +6144,7 @@ Please make sure you have read-permission to the file and the directory containi - With this knob you can set the coarse detuning of oscillator %1. You can detune the oscillator 12 semitones (1 octave) up and down. This is useful for creating sounds with a chord. + 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. @@ -8502,7 +8506,7 @@ This chip was used in the Commodore 64 computer. - PulseAudio (bad latency!) + PulseAudio diff --git a/data/locale/es.ts b/data/locale/es.ts index 5394c8973..3ba7312a3 100644 --- a/data/locale/es.ts +++ b/data/locale/es.ts @@ -3550,7 +3550,11 @@ Please visit http://lmms.sf.net/wiki for documentation on LMMS. - LMMS Project (*.mmpz *.mmp);;LMMS Project Template (*.mpt) + LMMS Project + + + + LMMS Project Template @@ -6140,8 +6144,8 @@ Please make sure you have read-permission to the file and the directory containi semitonos - With this knob you can set the coarse detuning of oscillator %1. You can detune the oscillator 12 semitones (1 octave) up and down. This is useful for creating sounds with a chord. - Con este control usted podrá establecer la desintonización gruesa del oscilador %1. Usted puede desintonizar el oscilador 12 semitonos (1 octava) arriba y abajo. Esto es útil para la creación de sonidos con acorde. + 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. + Con este control usted podrá establecer la desintonización gruesa del oscilador %1. Usted puede desintonizar el oscilador 24 semitonos (2 octavas) arriba y abajo. Esto es útil para la creación de sonidos con acorde. Osc %1 fine detuning left: @@ -8503,7 +8507,7 @@ This chip was used in the Commodore 64 computer. - PulseAudio (bad latency!) + PulseAudio diff --git a/data/locale/fa.ts b/data/locale/fa.ts index 50b3a3fad..50d1e790a 100644 --- a/data/locale/fa.ts +++ b/data/locale/fa.ts @@ -3550,7 +3550,11 @@ Please visit http://lmms.sf.net/wiki for documentation on LMMS. - LMMS Project (*.mmpz *.mmp);;LMMS Project Template (*.mpt) + LMMS Project + + + + LMMS Project Template @@ -6140,7 +6144,7 @@ Please make sure you have read-permission to the file and the directory containi - With this knob you can set the coarse detuning of oscillator %1. You can detune the oscillator 12 semitones (1 octave) up and down. This is useful for creating sounds with a chord. + 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 را تنظیم کنید.شما می توانید کوک نوسان ساز را در ۱۲ نیم صدا (۱ نت) بالا یا پایین کنید. این برای ایجاد صدا به همراه زه (Chord) مفید خواهد بود. @@ -8502,7 +8506,7 @@ This chip was used in the Commodore 64 computer. - PulseAudio (bad latency!) + PulseAudio diff --git a/data/locale/fr.ts b/data/locale/fr.ts index b2570b07c..6a3b0d36e 100644 --- a/data/locale/fr.ts +++ b/data/locale/fr.ts @@ -584,7 +584,7 @@ If you're interested in translating LMMS in another language or want to imp BBTrack Beat/Bassline %1 - Ryhtme ou ligne de basse %1 + Rythme ou ligne de basse %1 Clone of %1 @@ -3566,7 +3566,11 @@ Veuillez visiter http://lmms.sf.net/wiki pour la documentation de LMMS. - LMMS Project (*.mmpz *.mmp);;LMMS Project Template (*.mpt) + LMMS Project + + + + LMMS Project Template @@ -6162,8 +6166,8 @@ Veuillez vérifier que vous avez les droits en lecture pour ce fichier et le ré demi-tons - With this knob you can set the coarse detuning of oscillator %1. You can detune the oscillator 12 semitones (1 octave) up and down. This is useful for creating sounds with a chord. - Avec ce bouton vous pouvez régler le désaccord grossier de l'oscillateur %1. Vous pouvez désaccorder l'oscillateur de 12 demi-tons (1 octave) vers le haut et vers le bas. Ceci est utile pour la création de sons avec un accord. + 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. + Avec ce bouton vous pouvez régler le désaccord grossier de l'oscillateur %1. Vous pouvez désaccorder l'oscillateur de 24 demi-tons (2 octaves) vers le haut et vers le bas. Ceci est utile pour la création de sons avec un accord. Osc %1 fine detuning left: @@ -8537,7 +8541,7 @@ This chip was used in the Commodore 64 computer. - PulseAudio (bad latency!) + PulseAudio diff --git a/data/locale/gl.ts b/data/locale/gl.ts index c06249d2d..98c130485 100644 --- a/data/locale/gl.ts +++ b/data/locale/gl.ts @@ -3566,7 +3566,11 @@ Visitehttp://lmms.sf.net/wiki para documentación sobre o LMMS. - LMMS Project (*.mmpz *.mmp);;LMMS Project Template (*.mpt) + LMMS Project + + + + LMMS Project Template @@ -6161,8 +6165,8 @@ Asegúrese de ter permiso de lectura sobre o ficheiro e o directorio que o cont semitóns - With this knob you can set the coarse detuning of oscillator %1. You can detune the oscillator 12 semitones (1 octave) up and down. This is useful for creating sounds with a chord. - Con este botón pódese definir a desafinación bruta do oscilador %1. Pódese desafinar o oscilador 12 semitóns (unha oitava) para arriba e para abaixo. Isto é útil para crear sons cun acorde. + 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. + Con este botón pódese definir a desafinación bruta do oscilador %1. Pódese desafinar o oscilador 24 semitóns (2 oitavas) para arriba e para abaixo. Isto é útil para crear sons cun acorde. Osc %1 fine detuning left: @@ -8536,7 +8540,7 @@ Este chip empregábase no computador Commodore 64. - PulseAudio (bad latency!) + PulseAudio diff --git a/data/locale/it.ts b/data/locale/it.ts index fe49348ab..99bc63bf4 100644 --- a/data/locale/it.ts +++ b/data/locale/it.ts @@ -3574,8 +3574,12 @@ Visitare http://lmms.sf.net/wiki per la documentazione di LMMS. Rifai - LMMS Project (*.mmpz *.mmp);;LMMS Project Template (*.mpt) - Progetto LMMS (*mmpz *.mmp);;Progetto Template LMMS (*.mpt) + LMMS Project + Progetto LMMS + + + LMMS Project Template + Progetto Template LMMS My Projects @@ -6186,7 +6190,7 @@ Assicurarsi di avere i permessi in lettura per il file e per la directory che lo semitoni - With this knob you can set the coarse detuning of oscillator %1. You can detune the oscillator 12 semitones (1 octave) up and down. This is useful for creating sounds with a chord. + 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. Questa manopola regola l'intonazione, con la precisione di 1 semitono, dell'oscillatore %1. L'intonazione può essere variata di 24 semitoni (due ottave) in positivo e in negativo. Può essere usata per creare suoni con un accordo. @@ -8561,7 +8565,7 @@ Questo chip era utilizzato nel Commode 64. - PulseAudio (bad latency!) + PulseAudio diff --git a/data/locale/ja.ts b/data/locale/ja.ts index a568ffbbf..2aa1b1e50 100644 --- a/data/locale/ja.ts +++ b/data/locale/ja.ts @@ -3569,7 +3569,11 @@ Please visit http://lmms.sf.net/wiki for documentation on LMMS. - LMMS Project (*.mmpz *.mmp);;LMMS Project Template (*.mpt) + LMMS Project + + + + LMMS Project Template @@ -6165,7 +6169,7 @@ Please make sure you have read-permission to the file and the directory containi - With this knob you can set the coarse detuning of oscillator %1. You can detune the oscillator 12 semitones (1 octave) up and down. This is useful for creating sounds with a chord. + 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. @@ -8538,7 +8542,7 @@ This chip was used in the Commodore 64 computer. - PulseAudio (bad latency!) + PulseAudio diff --git a/data/locale/ko.ts b/data/locale/ko.ts index ad7ee413f..aea6c5611 100644 --- a/data/locale/ko.ts +++ b/data/locale/ko.ts @@ -3551,7 +3551,11 @@ LMMS 문서는 http://lmms.sf.net/wiki를 방문하세요. - LMMS Project (*.mmpz *.mmp);;LMMS Project Template (*.mpt) + LMMS Project + + + + LMMS Project Template @@ -6145,7 +6149,7 @@ Please make sure you have read-permission to the file and the directory containi - With this knob you can set the coarse detuning of oscillator %1. You can detune the oscillator 12 semitones (1 octave) up and down. This is useful for creating sounds with a chord. + 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. @@ -8507,7 +8511,7 @@ This chip was used in the Commodore 64 computer. - PulseAudio (bad latency!) + PulseAudio diff --git a/data/locale/nl.ts b/data/locale/nl.ts index e77143ee9..2b4416f46 100644 --- a/data/locale/nl.ts +++ b/data/locale/nl.ts @@ -3550,7 +3550,11 @@ Please visit http://lmms.sf.net/wiki for documentation on LMMS. - LMMS Project (*.mmpz *.mmp);;LMMS Project Template (*.mpt) + LMMS Project + + + + LMMS Project Template @@ -6144,8 +6148,8 @@ Zorg ervoor dat je schrijf-bevoegdheid hebt voor deze bestanden en mapen en prob semitonen - With this knob you can set the coarse detuning of oscillator %1. You can detune the oscillator 12 semitones (1 octave) up and down. This is useful for creating sounds with a chord. - Met deze knop stel je de grove ontstemming van oscillator %1 in. Je kunt de oscillator 12 seminote (1oktaaf) naar boven of beneden ontstemmen.Dit is bruikbaar voor het maken van geluiden met een akkoord. + 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. + Met deze knop stel je de grove ontstemming van oscillator %1 in. Je kunt de oscillator 24 seminote (2 oktaven) naar boven of beneden ontstemmen.Dit is bruikbaar voor het maken van geluiden met een akkoord. Osc %1 fine detuning left: @@ -8506,7 +8510,7 @@ This chip was used in the Commodore 64 computer. - PulseAudio (bad latency!) + PulseAudio diff --git a/data/locale/pl.ts b/data/locale/pl.ts index 9cab92906..60a86b97c 100644 --- a/data/locale/pl.ts +++ b/data/locale/pl.ts @@ -3571,7 +3571,11 @@ Odwiedź witrynę http://lmms.sf.net/wiki for documentation on LMMS. - LMMS Project (*.mmpz *.mmp);;LMMS Project Template (*.mpt) + LMMS Project + + + + LMMS Project Template @@ -6167,8 +6171,8 @@ Upewnij się, że masz uprawnienia do odczytu tego pliku i katalogu zawierające półtony - With this knob you can set the coarse detuning of oscillator %1. You can detune the oscillator 12 semitones (1 octave) up and down. This is useful for creating sounds with a chord. - Za pomocą tego pokrętła możesz ustawić zgrubne odstrojenie oscylatora %1. Możesz odstrajać oscylator o 12 półtonów (całą oktawę) w górę lub w dół. + 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. + Za pomocą tego pokrętła możesz ustawić zgrubne odstrojenie oscylatora %1. Możesz odstrajać oscylator o 24 półtonów (dwie oktawy) w górę lub w dół. Osc %1 fine detuning left: @@ -8542,7 +8546,7 @@ Te układy scalone były stosowane w komputerach Commodore 64. - PulseAudio (bad latency!) + PulseAudio diff --git a/data/locale/pt.ts b/data/locale/pt.ts index ecc6bfab7..b797a15d5 100644 --- a/data/locale/pt.ts +++ b/data/locale/pt.ts @@ -3569,7 +3569,11 @@ Por favor certifique-se que você tem permissão de escrita para este arquivo e - LMMS Project (*.mmpz *.mmp);;LMMS Project Template (*.mpt) + LMMS Project + + + + LMMS Project Template @@ -6117,8 +6121,8 @@ Por favor certifique-se que você tem permissões de leitura para o arquivo e pa Ajuste fino esquerdo Osc %1: - With this knob you can set the coarse detuning of oscillator %1. You can detune the oscillator 12 semitones (1 octave) up and down. This is useful for creating sounds with a chord. - Com este botão você pode modificar Ajuste bruto do oscilador %1. Você pode descer o tom do oscilador 12 semitons (1 oitava) para cima e para baixo. Isto é útil para criar sons com um acorde. + 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. + Com este botão você pode modificar Ajuste bruto do oscilador %1. Você pode descer o tom do oscilador 24 semitons (2 oitavas) para cima e para baixo. Isto é útil para criar sons com um acorde. Use phase modulation for modulating oscillator 3 with oscillator 2 @@ -8540,7 +8544,7 @@ Este chip foi utilizado no computador Commodore 64. - PulseAudio (bad latency!) + PulseAudio diff --git a/data/locale/ru.ts b/data/locale/ru.ts index a59fe4814..8d8fe034b 100644 --- a/data/locale/ru.ts +++ b/data/locale/ru.ts @@ -1,6 +1,6 @@ - + AboutDialog @@ -32,9 +32,13 @@ 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! - На этом языке не переведено (или установлен Английский). + Перевод выполнили: +Alexey Kouznetsov <alexey/dot/kouznetsov/at/gmail/dot/com> +Oe Ai <oeai/at/symbiants/dot/com> -Если Вы заинтересованы в переводе LMMS на другой язык или хотите улучшить существующий перевод, мы приветствуем любую помощь! Просто свяжитесь с разработчиками! +Музыкльные термины можно нйти в словаре dic.academic.ru/dic.nsf/enc_colier/6207/ТЕРМИНЫ +Если Вы заинтересованы в переводе LMMS на другой язык или хотите улучшить существующий перевод, мы приветствуем любую помощь! Просто свяжитесь с разработчиками! + License @@ -50,15 +54,15 @@ If you're interested in translating LMMS in another language or want to imp LMMS - ЛММС + ЛММС Involved - Участники + Участники Contributors ordered by number of commits: - Разработчики сортированные по числу коммитов: + Разработчики сортированные по числу коммитов: @@ -69,7 +73,7 @@ If you're interested in translating LMMS in another language or want to imp Volume: - Громкость: + Громкость: PAN @@ -77,42 +81,42 @@ If you're interested in translating LMMS in another language or want to imp Panning: - + Балансировка: LEFT - + Лево Left gain: - + Лево мощность: RIGHT - + Право Right gain: - + Право мощность: AmplifierControls Volume - Громкость + Громкость Panning - + Баланс Left gain - + Лево мощн Right gain - + Право мощн @@ -171,39 +175,39 @@ If you're interested in translating LMMS in another language or want to imp Disable loop - + Отключить петлю This button disables looping. The sample plays only once from start to end. - + Эта кнопка отключает петлю (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. - + Эта кнопка включает пинг-понг петлю. Сэмпл кольцуется обратно и вперёд между конечной точкой и точкой петли. 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. - + Этот регулятор устанавливает точку в которой АудиоФайлПроцессор должен перестать воспроизвдение сэмпла. Loopback point: - + Точка возврата петли: With this knob you can set the point where the loop starts. - + Этот регулятор ставит точку начала петли. @@ -233,11 +237,11 @@ If you're interested in translating LMMS in another language or want to imp CLIENT-NAME - ИМЯ КЛИЕНТА + ИМЯ КЛИЕНТА CHANNELS - КАНАЛЫ + КАНАЛЫ @@ -347,109 +351,109 @@ 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. - Нажмите здесь, если вы хотите остановить воспроизведение текущего шаблона. + Нажмите здесь, если вы хотите остановить воспроизведение текущей мелодии. Draw mode (Shift+D) - Режим рисования (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 (Ctrl+X) - Вырезать выбранные ноты (Ctrl+X) + Вырезать выбранные ноты (Ctrl+X) Copy selected values (Ctrl+C) - Копировать выбранные ноты в буфер (Ctrl+C) + Копировать выбранные ноты в буфер (Ctrl+C) Paste values from clipboard Ctrl+V) - + Вставить запомненные значения (Ctrl+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: @@ -457,11 +461,11 @@ If you're interested in translating LMMS in another language or want to imp Automation Editor - no pattern - Редактор автоматизаци — нет шаблона + Редактор автоматизаци — нет шаблона Automation Editor - %1 - Редактор автоматизации — %1 + Редактор автоматизации — %1 @@ -472,14 +476,15 @@ If you're interested in translating LMMS in another language or want to imp Model is already connected to this pattern. - + паттерн - шаблон, мелодия + Модель уже подключена к этому шаблону. AutomationPatternView double-click to open this pattern in automation editor - Дважды щёлкните мышью чтобы настроить автоматизацию для этого шаблона + Дважды щёлкните мышью чтобы настроить автоматизацию этого шаблона Open in Automation editor @@ -507,15 +512,15 @@ If you're interested in translating LMMS in another language or want to imp Set/clear record - Установить/очистить запись + Установить/очистить запись Flip Vertically (Visible) - + Перевернуть вертикально (Видимое) Flip Horizontally (Visible) - + Перевернуть горизонтально (Видимое) @@ -529,115 +534,115 @@ If you're interested in translating LMMS in another language or want to imp BBEditor Beat+Bassline Editor - Ритм Басс Редактор + Ритм+Бас Редактор Play/pause current beat/bassline (Space) - Игра/пауза текущей линии ритма/басса (<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 - + Добавить такты BBTCOView Open in Beat+Bassline-Editor - Открыть в редакторе ритма и басса + Открыть в редакторе ритм + баса Reset name - Сбросить название + Сбросить название Change name - Переименовать + Переименовать Change color - Изменить цвет + Изменить цвет Reset color to default - + Установить цвет по умолчанию BBTrack Beat/Bassline %1 - Ритм-Басс Линия %1 + Ритм-Бас Линия %1 Clone of %1 - Копия %1 + Копия %1 BassBoosterControlDialog FREQ - + ЧАСТ Frequency: - Частота: + Частота: GAIN - УСИЛ + МОЩ Gain: - Усиление: + Мощность: RATIO - ОТН + ОТН Ratio: - Отношение: + Отношение: BassBoosterControls Frequency - Частота + Частота Gain - Усиление + Мощность Ratio - Отношение + Отношение @@ -652,11 +657,11 @@ If you're interested in translating LMMS in another language or want to imp GAIN - УСИЛ + Input Gain: - + Входная мощность: NOIS @@ -664,7 +669,7 @@ If you're interested in translating LMMS in another language or want to imp Input Noise: - + Входной шум: Output Gain: @@ -712,37 +717,37 @@ If you're interested in translating LMMS in another language or want to imp Stereo difference: - + Стерео разница: Levels - + Уровни Levels: - + Уровни: CaptionMenu &Help - &H Справка + &H Справка Help (not available) - + Справка (не доступна) CarlaInstrumentView Show GUI - Показать интерфейс + Показать интерфейс Click here to show or hide the graphical user interface (GUI) of Carla. - + Нажмите сюда, чтобы показать или скрыть графический интерфейс Карла. @@ -920,11 +925,11 @@ If you're interested in translating LMMS in another language or want to imp DelayControls Delay Samples - + Задержка сэмплов Feedback - + Возврат Lfo Frequency @@ -939,11 +944,11 @@ If you're interested in translating LMMS in another language or want to imp DelayControlsDialog Delay - + Задержка Delay Time - + Время задержки Regen @@ -970,26 +975,26 @@ If you're interested in translating LMMS in another language or want to imp DetuningHelper Note detuning - + Расстройка нот DualFilterControlDialog Filter 1 enabled - + Фильтр 1 включен Filter 2 enabled - + Фильтр 2 включен Click to enable/disable Filter 1 - + Кликнуть для включения/выключения Фильтра 1 Click to enable/disable Filter 2 - + Кликнуть для включения/выключения Фильтра 2 @@ -1131,26 +1136,26 @@ If you're interested in translating LMMS in another language or want to imp DummyEffect NOT FOUND - + НЕ НАЙДЕН Editor Play (Space) - + Игра (Пробел) Stop (Space) - + Стоп (Пробел) Record - + Запись Record while playing - + Запись при игре @@ -1532,18 +1537,18 @@ Right clicking will bring up a context menu where you can change the order in wh Click here for random wave. - + Нажмите сюда для случайной волны. EqControls Input gain - + Входная мощность Output gain - + Выходная мощность Low shelf gain @@ -1738,7 +1743,7 @@ Right clicking will bring up a context menu where you can change the order in wh Gain - Усиление + Мощность Out Gain @@ -1746,15 +1751,15 @@ Right clicking will bring up a context menu where you can change the order in wh Bandwidth: - + Полоса: Resonance : - + Резонанс: Frequency: - Частота: + Частота: 12dB @@ -1781,7 +1786,7 @@ Right clicking will bring up a context menu where you can change the order in wh EqParameterWidget Hz - + Гц @@ -1924,74 +1929,74 @@ Right clicking will bring up a context menu where you can change the order in wh 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 для записи. + Не могу открыть файл %1 для записи. Проверьте, обладаете ли вы правами на запись в выбранный файл и содержащий его каталог и попробуйте снова! Export project to %1 - Экспорт проекта в %1 + Экспорт проекта в %1 Error - Ошибка + Ошибка Error while determining file-encoder device. Please try to choose a different output format. - Ошибка при определении кодека файла. Попробуйте выбрать другой формат вывода. + Ошибка при определении кодека файла. Попробуйте выбрать другой формат вывода. Rendering: %1% - Обработка: %1% + Обработка: %1% Fader Please enter a new value between %1 and %2: - Введите новое значение от %1 до %2: + Введите новое значение от %1 до %2: FileBrowser Browser - Обозреватель файлов + Обозреватель файлов 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... - Пж. ждите, запись загружается для просмотра... + Пж. ждите, запись загружается для просмотра... --- Factory files --- - --- Заводские файлы --- + --- Заводские файлы --- @@ -2025,11 +2030,11 @@ Please make sure you have write-permission to the file and the directory contain FlangerControlsDialog Delay - + Задержка Delay Time: - + Время задержки: Lfo Hz @@ -2061,14 +2066,14 @@ Please make sure you have write-permission to the file and the directory contain White Noise Amount: - + Объём белого шума: FxLine Channel send amount - + Величина отправки канала The FX channel receives input from one or more instrument tracks. @@ -2078,27 +2083,31 @@ In order to route the channel to another channel, select the FX channel and clic You can remove and move FX channels in the context menu, which is accessed by right-clicking the FX channel. - + Канал эффектов (ЭФ) получает сигнал на вход от одной или нескольких инструментальных дорожек. +В свою очередь его можно подключить к нескольким другим каналам эффектов. ЛММС автоматически предотвращает бесконечные циклы и не позволяет создавать соединения, которые приведут к бесконечному циклу. +Чтобы соединить один канал с другим, выберите канал ЭФфектов и кликните кнопку послать (Send) на канале, куда нужно послать. Регулятор под кнопкой "послать" контролирует уровень сигнала, посылаемого на канал. +Можно убирать и двигать каналы эффектов через контекстное меню, если кликнуть правой кнопкой мыши по каналу эффектов. + Move &left - + Двигать влево &L Move &right - + Двигать вправо &r Rename &channel - + Переименовать канал &c R&emove channel - + Удалить канал &e Remove &unused channels - + Удалить неиспользуемые каналы &u @@ -2144,76 +2153,76 @@ You can remove and move FX channels in the context menu, which is accessed by ri Solo FX channel - + Соло канал ЭФ FxRoute Amount to send from channel %1 to channel %2 - + Величина отправки с канала %1 на канал %2 GigInstrument Bank - Банк + Банк Patch - Патч + Патч Gain - Усиление + Мощность 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) @@ -2276,7 +2285,7 @@ You can remove and move FX channels in the context menu, which is accessed by ri Down and up - + Вниз и вверх @@ -2394,7 +2403,7 @@ You can remove and move FX channels in the context menu, which is accessed by ri 6 - 8х {6?} + 6sus4 @@ -2414,7 +2423,7 @@ You can remove and move FX channels in the context menu, which is accessed by ri 7 - 8х {7?} + 7sus4 @@ -2797,15 +2806,15 @@ You can remove and move FX channels in the context menu, which is accessed by ri CUSTOM BASE VELOCITY - + ПРОИЗВОЛЬНАЯ БАЗОВАЯ СКОРОСТЬ Specify the velocity normalization base for MIDI-based instruments at note volume 100% - + Опрделяет базовую скорость нормальизации для MiDi инструментов при громкости ноты 100% BASE VELOCITY - + БАЗОВАЯ СКОРОСТЬ @@ -2816,7 +2825,7 @@ You can remove and move FX channels in the context menu, which is accessed by ri Enables the use of Master Pitch - + Включает использование основной тональности @@ -2856,7 +2865,7 @@ You can remove and move FX channels in the context menu, which is accessed by ri Q/Resonance или качество? - Кол./Резонанса + LowPass @@ -2996,7 +3005,7 @@ You can remove and move FX channels in the context menu, which is accessed by ri Envelopes, LFOs and filters are not supported by the current instrument. - + Огибающие, LFO и фильтры не поддерживаются этим инструментом. @@ -3165,38 +3174,38 @@ You can remove and move FX channels in the context menu, which is accessed by ri 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. - + Нажать здесь, чтобы сохранить настройки текущей инстр. дорожки в файл предустановок. Позже можно загрузить эту предустановку двойным кликом в браузере предустановок. MISC - РАЗНОЕ + РАЗН Knob Set linear - + Установить линейно Set logarithmic - + Установить логарифмически Please enter a new value between -96.0 dBV and 6.0 dBV: - Введите новое значение от –96,0 дБВ до 6,0 дБВ: + Введите новое значение от –96,0 дБВ до 6,0 дБВ: Please enter a new value between %1 and %2: - Введите новое значение от %1 до %2: + Введите новое значение от %1 до %2: @@ -3243,7 +3252,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: + Введите новое значение от %1 до %2: @@ -3376,7 +3385,7 @@ Double click to pick a file. Click here for a moog saw-wave. - + Нажать здесь для зигзагообразной муг волны. @@ -3490,11 +3499,11 @@ Please make sure you have write-access to the file and try again. 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. - Сим запускается ритм-басс редактор. Он необходим для установки ритма, открытия, добавления и удаления каналов, а также вырезания, копирования и вставки ритм-басс шаблонов и т. п. + Сим запускается ритм-бас редактор. Он необходим для установки ритма, открытия, добавления и удаления каналов, а также вырезания, копирования и вставки ритм-бас шаблонов, мелодий и т. п. Show/hide Piano-Roll @@ -3576,75 +3585,80 @@ Please visit http://lmms.sf.net/wiki for documentation on LMMS. Volumes - + Объёмы? + Громкости Undo - + Откатить действие Redo + Возврат действия + + + LMMS Project - LMMS Project (*.mmpz *.mmp);;LMMS Project Template (*.mpt) + LMMS Project Template My Projects - + Мои проекты My Samples - + Мои сэмплы My Presets - + Мои предустановки My Home - + Моя домашняя папка My Computer - + Мой компьютер Root Directory - + Корневая директория &File - + &F Файл &Recently Opened Projects - + &R Недавние проекты Save as New &Version - + &V Сохранить как новую версию E&xport Tracks... - + &x Экспорт дорожек... Online Help - + Помощь онлайн What's This? - + Что это? Open Project - + Открыть проект Save Project - + Сохранить проект @@ -3686,7 +3700,7 @@ Please visit http://lmms.sf.net/wiki for documentation on LMMS. MidiAlsaSeq DEVICE - УСТРОЙСТВО + УСТРОЙСТВО @@ -3767,7 +3781,7 @@ Please visit http://lmms.sf.net/wiki for documentation on LMMS. Base velocity - + Базовая скорость @@ -4249,17 +4263,19 @@ 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. @@ -4267,153 +4283,171 @@ Knobs and other widgets in the Operators view have their own what's this -t 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. - + Матричный вид содержит матрицу модуляции. Здесь можно определить модуляционное отношение между разными операторами. Каждый слышимый оператор (осцилляторы 1-3) имеют 3-4 свойства, которые можно модулировать любыми модуляторами. Используя больше модуляций увеличивается нагрузка на процессор. + +Вид делится на цели модуляции, сгруппированные на целевой осциллятор. Доступные цели : громкость, тон, фаза, ширина пульсации и отношение с подчиненным (под-) осциллятором. Отметим что некоторые цели определены только для одного осциллятора. + +Каждая цель модуляции имеет 4 регулятора, один на каждый модулятор. По умолчанию регуляторы установлены на 0, то есть без модуляции. Включая регулятор на 1 ведёт к тому, что модулятор влияет на цель модуляции на столько на сколько возможно. Включая его на -1 делает то же, но с обратной модуляцией. 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. - + В дополнение к выделенным модуляторам Монстро позволяет выходу осциллятора 2 модулировать осцллятор 3. + +Смешанный (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. - + В дополнение к выделенным модуляторам Монстро позволяет выходу осциллятора 2 модулировать осцллятор 3. + +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. - + В дополнение к выделенным модуляторам Монстро позволяет выходу осциллятора 2 модулировать осцллятор 3. + +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. - + В дополнение к выделенным модуляторам Монстро позволяет выходу осциллятора 2 модулировать осцллятор 3. + +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 (НизкоЧастотныйГенератор). +"Random" (Случайно) и "Random-smooth" (случайное сглаживание) - это специальные волны: они создают случаный сигнал, где частота LFO контролирует как часто изменяется состояние генератора (LFO). +Сглаженная версия переходит между этими состояниями с косинусоидальной интерплояцией. Эти случайные режимы могут быть использованы, чтобы дать "жизни" вашим настройкам - добавить немного аналоговой непредсказуемости... 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 (НизкоЧастотныйГенератор). +"Random" (Случайно) и "Random-smooth" (случайное сглаживание) - это специальные волны: они создают случаный сигнал, где частота LFO контролирует как часто изменяется состояние генератора (LFO). +Сглаженная версия переходит между этими состояниями с косинусоидальной интерплояцией. Эти случайные режимы могут быть использованы, чтобы дать "жизни" вашим настройкам - добавить немного аналоговой непредсказуемости... 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 создаёт прямые подъёмы и спады. Отрицательные величины создают кривые с замедленным началом, быстрым пиком и снова замедленным спадом. Позитивные значения создают кривые которые начинаются и кончаются быстро, но долбше остаются на пиках. @@ -4448,7 +4482,7 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator Swap left and right input channel for reflections - + Поменять вход левого и правого канала для отзвуков @@ -4578,7 +4612,7 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator Osc %1 harmonic - + Осц %1 гармонический @@ -4633,8 +4667,8 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator double-click to open this pattern in piano-roll use mouse wheel to set volume of a step - Чтобы открыть этот шаблон в нотном редакторе, дважды на нём щёлкните -Используйте колёсико мыши для установки громкости отдельного шага + Чтобы открыть эту мелодию в нотном редакторе, дважды на нём щёлкните +Используйте колёсико мыши для установки громкости отдельного такта Open in piano-roll @@ -4654,11 +4688,11 @@ use mouse wheel to set volume of a step Add steps - Добавить шаги + Добавить такты Remove steps - Удалить шаги + Удалить такты @@ -4770,14 +4804,14 @@ use mouse wheel to set volume of a step Treshold - + Порог PianoRoll Piano-Roll - no pattern - Нотный редактор - без шаблона + Нотный редактор - нет мелодии Piano-Roll - %1 @@ -4785,7 +4819,7 @@ use mouse wheel to set volume of a step Please open a pattern by double-clicking on it! - Откройте шаблон с помощью двойного щелчка мышью! + Откройте мелодию с помощью двойного щелчка мышью! Last note @@ -4829,135 +4863,135 @@ use mouse wheel to set volume of a step Volume: %1% - + Громкость %1% Panning: %1% left - + Баланс: %1% лево Panning: %1% right - + Баланс: %1% право Panning: center - + Баланс: центр Please enter a new value between %1 and %2: - Введите новое значение от %1 до %2: + Введите новое значение от %1 до %2: PianoRollWindow Play/pause current pattern (Space) - + Игра/Пауза текущей мелодии (Пробел) Record notes from MIDI-device/channel-piano - Записать ноты с цифрового музыкального инструмента (MIDI) + Записать ноты с музыкального инструмента (MIDI)/канала Record notes from MIDI-device/channel-piano while playing song or BB track - Записать ноты с цифрового музыкального инструмента (MIDI) во время воспроизведения композиции или дорожки Ритм-Басса + Записать ноты с цифрового музыкального инструмента (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 или виртуального синтезатора соответствующего канала. Позже вы сможете отредактировать записанный шаблон. + Нажмите эту кнопку, если вы хотите записать ноты с устройства 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 или виртуального синтезатора соответствующего канала. Во время записи все ноты записываются в этот шаблон, и вы будете слышать композицию или РБ дорожку на заднем плане. + Нажмите эту кнопку, если вы хотите записать ноты с устройства MIDI или виртуального синтезатора соответствующего канала. Во время записи все ноты записываются в эту мелодию, и вы будете слышать композицию или РБ дорожку на заднем плане. Click here to stop playback of current pattern. - Нажмите здесь, если вы хотите остановить воспроизведение текущего шаблона. + Нажмите здесь, если вы хотите остановить воспроизведение текущей мелодии. Draw mode (Shift+D) - Режим рисования (Shift+D) + Режим рисования (Shift+D) Erase mode (Shift+E) - + Режим стирания (Shift+E) Select mode (Shift+S) - Режим выбора нот (Shift+S) + Режим выбора нот (Shift+S) Detune mode (Shift+T) - Режим подстраивания (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 Ctrl to temporarily go into select mode. - Режим рисования нот, в нём вы можете добавлять/перемещать и изменять длительность одиночных нот. Это режим по умолчанию и используется большую часть времени. + Режим рисования нот, в нём вы можете добавлять/перемещать и изменять длительность одиночных нот. Это режим по умолчанию и используется большую часть времени. Для включения этого режима можно использовать комбинацию клавиш Shift+D, удерживайте Ctrl для временного переключения в режим выбора. 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. + Режим стирания. В этом режиме вы можете стирать ноты. Для включения этого режима можно использовать комбинацию клавиш Shift+E. Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold Ctrl in draw mode to temporarily use select mode. - Режим выделения. В этом режиме можно выделять ноты, можно также удерживать Ctrl в режиме рисования, чтобы можно было на время войти в режим выделения. + Режим выделения. В этом режиме можно выделять ноты, можно также удерживать Ctrl в режиме рисования, чтобы можно было на время войти в режим выделения. 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>. + Режим подстройки. В этом режиме можно выбирать ноты для автоматизации их подстраивания. Можно использовать это для переходов нот от одной к другой. Для активации с клавиатуры <Shift+T>. Cut selected notes (Ctrl+X) - Переместить выделенные ноты в буфер (Ctrl+X) + Переместить выделенные ноты в буфер (Ctrl+X) Copy selected notes (Ctrl+C) - Копировать выделенные ноты в буфер (Ctrl+X) + Копировать выделенные ноты в буфер (Ctrl+X) Paste notes from clipboard (Ctrl+V) - Вставить ноты из буфера (Ctrl+V) + Вставить ноты из буфера (Ctrl+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 затем сможет нарисовать или подсветить. В этом меню можно найти ниболее популярные аккорды. После того, как вы выбрали аккорд, кликните в любом месте, чтобы поставить его и правым кликом по виртуальной клавиатуре открывается контекстное меню и подсветка аккорда. Для возврата в режим одной ноты нужно выбрать "Без аккорда" в этом выпадающем меню. @@ -4989,117 +5023,117 @@ Reason: "%2" LMMS plugin %1 does not have a plugin descriptor named %2! - + ЛММС плагин %1 не имеет описания плагина с именем %2! PluginBrowser Instrument plugins - Инструменты + Плагины инструментов Instrument browser - Обзор инструментов + Обзор инструментов Drag an instrument into either the Song-Editor, the Beat+Bassline Editor or into an existing instrument track. - Вы можете переносить нужные вам инструменты из этой панели в музыкальный, ритм-басс редактор или в существующую дорожку инструмента. + Вы можете переносить нужные вам инструменты из этой панели в музыкальный, ритм-бас редактор или в существующую дорожку инструмента. ProjectNotes Project notes - Заметки к проекту + Заметки к проекту Put down your project notes here. - Здесь вы можете держать заметки к своему проекту. + Здесь вы можете держать заметки к своему проекту. Edit Actions - Правка + Правка &Undo - &U Отменить + &U Отменить Ctrl+Z - Ctrl+Z + Ctrl+Z &Redo - &R Повторить + &R Повторить Ctrl+Y - Ctrl+Y + Ctrl+Y &Copy - &C Копировать + &C Копировать Ctrl+C - Ctrl+C + Ctrl+C Cu&t - &t Вырезать + &t Вырезать Ctrl+X - Ctrl+X + Ctrl+X &Paste - &P Вставить + &P Вставить Ctrl+V - Ctrl+V + Ctrl+V Format Actions - Форматирование + Форматирование &Bold - Полу&жирный + &b Полужирный Ctrl+B - Ctrl+B + Ctrl+B &Italic - &Курсив + &i Курсив Ctrl+I - + Ctrl+I &Underline - &Подчеркнуть + &U Подчеркнутый Ctrl+U - + Ctrl+U &Left - По &левому краю + &L По левому краю Ctrl+L - + Ctrl+L C&enter - По &центру + По &центру Ctrl+E @@ -5261,7 +5295,7 @@ Reason: "%2" In Place Broken: - Вместо сломанного: + Вместо сломанного: Channels In: @@ -5273,14 +5307,14 @@ Reason: "%2" File: %1 - + Файл: %1 RenameDialog Rename... - Переименовать... + Переименовать... @@ -5327,7 +5361,7 @@ Reason: "%2" All Audio-Files (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw) - + Все аудио файлы (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw) @@ -5374,7 +5408,7 @@ Reason: "%2" Panning - + Баланс @@ -5393,162 +5427,162 @@ Reason: "%2" Panning - + Баланс Panning: - + Баланс: PAN - БАЛ + БАЛ SetupDialog Setup LMMS - Настройка LMMS + Настройка LMMS General settings - Общие параметры + Общие параметры BUFFER SIZE - РАЗМЕР БУФЕРА + РАЗМЕР БУФЕРА Reset to default-value - Восстановить значение по умолчанию + Восстановить значение по умолчанию MISC - РАЗНОЕ + РАЗНОЕ Enable tooltips - Включить подсказки + Включить подсказки Show restart warning after changing settings - Показывать предупреждение о перезапуске при изменении настроек + Показывать предупреждение о перезапуске при изменении настроек Display volume as dBV - Отображать громкости в децибелах (напр.) + Отображать громкость в децибелах dBV 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 плагины с хостом воспроизведения + Синхронизировать 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 - + Создать запасной файл при сохранении проекта LANGUAGE - + ЯЗЫК Paths - Пути + Пути LMMS working directory - Рабочий каталог LMMS + Рабочий каталог LMMS VST-plugin directory - Каталог модулей VST + Каталог модулей VST Artwork directory - Каталог с элементами оформления + Каталог с элементами оформления Background artwork - Фоновое изображение + Фоновое изображение FL Studio installation directory - Каталог установки FL Studio + Каталог установки FL Studio LADSPA plugin paths - Пути модулей LADSPA + Пути модулей LADSPA STK rawwave directory - Каталог STK rawwave + Каталог STK rawwave Default Soundfont File - Основной Soundfont файл + Основной Soundfont файл Performance settings - Параметры производительности + Параметры производительности UI effects vs. performance - Визуальные эффекты/производительность + Визуальные эффекты/производительность Smooth scroll in Song Editor - Плавная прокрутка в музыкальном редакторе + Плавная прокрутка в музыкальном редакторе Enable auto save feature - Включить функцию авто-сохранения + Включить функцию авто-сохранения Show playback cursor in AudioFileProcessor - Показывать указатель воспроизведения в процессоре аудио файлов + Показывать указатель воспроизведения в процессоре аудио файлов (AFP) Audio settings - Параметры звука + Параметры звука AUDIO INTERFACE - ЗВУКОВАЯ СИСТЕМА + ЗВУКОВАЯ СИСТЕМА MIDI settings - Параметры MIDI + Параметры MIDI MIDI INTERFACE - ИНТЕРФЕЙС MIDI + MIDI СИСТЕМА OK @@ -5556,65 +5590,65 @@ Reason: "%2" Cancel - Отменить + Отменить Restart LMMS - Перезапустите LMMS + Перезапустить LMMS Please note that most changes won't take effect until you restart LMMS! - Учтите, что большинство настроек не вступят в силу до перезапуска программы! + Учтите, что большинство настроек не вступят в силу до перезапуска ЛММС! Frames: %1 Latency: %2 ms - Фрагментов: %1 + Фрагментов: %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. Меньшие значения дают меньшее время отклика программы, но повышают потребление ресурсов - это особенно заметно на старых машинах и системах, ядро которых не поддерживает приоритета реального времени. Если наблюдается прерывистый звук, попробуйте увеличить размер буфера. + Здесь вы можете настроить размер внутреннего звукового буфера LMMS. Меньшие значения дают меньшее время отклика программы, но повышают потребление ресурсов - это особенно заметно на старых машинах и системах, ядро которых не поддерживает приоритета реального времени. Если наблюдается прерывистый звук, попробуйте увеличить размер буфера. Choose LMMS working directory - Выбор рабочего каталога LMMS + Выбор рабочего каталога LMMS Choose your VST-plugin directory - Выбор своего каталога для модулей VST + Выбор своего каталога для модулей VST Choose artwork-theme directory - Выбор каталога с темой оформления для LMMS + Выбор каталога с темой оформления для LMMS Choose FL Studio installation directory - Выбор каталога установленной FL Studio + Выбор каталога установленной FL Studio Choose LADSPA plugin directory - Выбор каталога с модулями LADSPA + Выбор каталога с модулями LADSPA Choose STK rawwave directory - Выбор каталога STK rawwave + Выбор каталога STK rawwave Choose default SoundFont - Выбрать главный 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 и другие. В нижней части окна настройки можно задать специфические параметры выбранной системы. + Пожалуйста, выберите желаемую звуковую систему. В зависимости от конфигурации во время компилирования программы вы можете использовать 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. В зависимости от конфигурации во время компилирования программы вы можете использовать ALSA, OSS и другие. В нижней части окна настройки можно задать специфические параметры выбранного интерфейса. @@ -5633,63 +5667,63 @@ Latency: %2 ms Project saved - Проект сохранён + Проект сохранён The project %1 is now saved. - Проект %1 сохранён. + Проект %1 сохранён. Project NOT saved. - Проект НЕ СОХРАНЁН. + Проект НЕ СОХРАНЁН. The project %1 was not saved! - Проект %1 не сохранён! + Проект %1 не сохранён! Import file - Импорт файла + Импорт файла MIDI sequences - MiDi последовательности + MiDi последовательности FL Studio projects - FL Studio проекты + FL Studio проекты Hydrogen projects - Hydrogen проекты + 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: - + Следующие ошибки возникли при загрузке: @@ -5769,84 +5803,84 @@ Latency: %2 ms 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. - Нажмите сюда, если вы хотите остановить воспроизведение мелодии. Курсор при этом будет установлен на начало композиции. + Нажмите сюда, если вы хотите остановить воспроизведение мелодии. Курсор при этом будет установлен на начало композиции. SpectrumAnalyzerControlDialog Linear spectrum - Линейный спектр + Линейный спектр Linear Y axis - Линейная ось ординат + Линейная ось ординат (Y) SpectrumAnalyzerControls Linear spectrum - Линейный спектр + Линейный спектр Linear Y axis - Линейная ось ординат + Линейная ось ординат (Y) Channel mode - Режим канала + Режим канала TabWidget Settings for %1 - + Настройки для %1 @@ -5935,46 +5969,46 @@ Latency: %2 ms 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 <Ctrl> to disable magnetic loop points. - Нажмите <Ctrl>, чтобы убрать прилипание точек цикла + Нажмите <Ctrl>, чтобы убрать прилипание точек петли. Hold <Shift> to move the begin loop point; Press <Ctrl> to disable magnetic loop points. - Зажмите <Shift> чтобы сдвинуть начало точек цикла; Нажмите <Ctrl>, чтобы убрать прилипание точек цикла + Зажмите <Shift> чтобы сдвинуть начало точек петли; Нажмите <Ctrl>, чтобы убрать прилипание точек петли. Track Muted - Тихо + Тихо Solo - Соло + Соло @@ -6024,101 +6058,101 @@ Please make sure you have read-permission to the file and the directory containi TrackContentObject Muted - Тихо + Тихо TrackContentObjectView Current position - Позиция + Текущая позиция Hint - Подсказка + Подсказка Press <Ctrl> and drag to make a copy. - Нажмите <Ctrl> и перетащите, чтобы создать копию. + Нажмите <Ctrl> и тащите мышью, чтобы создать копию. Current length - Длительность + Текущая длительность Press <Ctrl> for free resizing. - Для свободного изменения размера нажмите <Ctrl>. + Для свободного изменения размера нажмите <Ctrl>. %1:%2 (%3:%4 to %5:%6) - %1:%2 (от %3:%4 до %5:%6) + %1:%2 (от %3:%4 до %5:%6) Delete (middle mousebutton) - Удалить (средняя кнопка мыши) + Удалить (средняя кнопка мыши) Cut - Вырезать + Вырезать Copy - Копировать + Копировать Paste - Вставить + Вставить Mute/unmute (<Ctrl> + middle click) - + Тихо/громко (<Ctrl> + middle click) TrackOperationsWidget Press <Ctrl> while clicking on move-grip to begin a new drag'n'drop-action. - Зажмите <Сtrl> и нажимайте мышь во время движения, чтобы начать новую переброску. + Зажмите <Сtrl> и нажимайте мышь во время движения, чтобы начать новую переброску. Actions for this track - Действия для этой дорожки + Действия для этой дорожки Mute - Заглушить + Тихо Solo - Соло + Соло Mute this track - Отключить дорожку + Заглушить эту дорожку Clone this track - Клонировать дорожку + Клонировать дорожку Remove this track - Удалить дорожку + Удалить дорожку Clear this track - + Очистить эту дорожку FX %1: %2 - + ЭФ %1: %2 Turn all recording on - + Включить всё на запись Turn all recording off - + Выключить всю запись @@ -6188,8 +6222,8 @@ Please make sure you have read-permission to the file and the directory containi полутон[а,ов] - With this knob you can set the coarse detuning of oscillator %1. You can detune the oscillator 12 semitones (1 octave) up and down. This is useful for creating sounds with a chord. - Грубая регулировка подстройки осциллятора %1. Возможна подстройка до 12 полутонов (до одной октавы) вверх и вниз. Полезно для создания аккордов. + 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: @@ -6370,11 +6404,11 @@ 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 - Нажать для включения + Нажать для включения @@ -6480,11 +6514,11 @@ Please make sure you have read-permission to the file and the directory containi Please wait while loading VST plugin... - + Пожалуйста, подождите пока грузится VST плагин... The VST plugin %1 could not be loaded. - + VST плагин %1 не может быть загружен. @@ -6603,7 +6637,7 @@ Please make sure you have read-permission to the file and the directory containi Selected graph - + Выбранный граф @@ -6630,15 +6664,15 @@ Please make sure you have read-permission to the file and the directory containi 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 @@ -6646,19 +6680,19 @@ Please make sure you have read-permission to the file and the directory containi 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 @@ -6666,11 +6700,11 @@ Please make sure you have read-permission to the file and the directory containi Click to load a waveform from a sample file - + Кликнуть для загрузки формы звука из файла с образцом Phase left - + Фаза слева Click to shift phase by -15 degrees @@ -6678,7 +6712,7 @@ Please make sure you have read-permission to the file and the directory containi Phase right - + Фаза справа Click to shift phase by +15 degrees @@ -6686,7 +6720,7 @@ Please make sure you have read-permission to the file and the directory containi Normalize - Нормализовать + Нормализовать Click to normalize @@ -6702,7 +6736,7 @@ Please make sure you have read-permission to the file and the directory containi Smooth - Сгладить + Сгладить Click to smooth @@ -6710,7 +6744,7 @@ Please make sure you have read-permission to the file and the directory containi Sine wave - Синусоида + Синусоида Click for sine wave @@ -6984,7 +7018,7 @@ Please make sure you have read-permission to the file and the directory containi Input gain: - + Входная мощность: OUTPUT @@ -6992,7 +7026,7 @@ Please make sure you have read-permission to the file and the directory containi Output gain: - + Выходная мощность: ATTACK @@ -7000,7 +7034,7 @@ Please make sure you have read-permission to the file and the directory containi Peak attack time: - + Время пиковой атаки: RELEASE @@ -7008,7 +7042,7 @@ Please make sure you have read-permission to the file and the directory containi Peak release time: - + Время отпуска пика: Reset waveform @@ -7016,7 +7050,7 @@ Please make sure you have read-permission to the file and the directory containi Click here to reset the wavegraph back to default - + Нажмите здесь, чтобы скинуть граф волны обратно по умолчанию Smooth waveform @@ -7024,7 +7058,7 @@ Please make sure you have read-permission to the file and the directory containi Click here to apply smoothing to wavegraph - + Нажмите здесь, чтобы применить сглаживание графа волны Increase wavegraph amplitude by 1dB @@ -7032,7 +7066,7 @@ Please make sure you have read-permission to the file and the directory containi Click here to increase wavegraph amplitude by 1dB - + Нажмите здесь, чтобы увеличить амплитуду графа волны на 1дБ Decrease wavegraph amplitude by 1dB @@ -7040,7 +7074,7 @@ Please make sure you have read-permission to the file and the directory containi Click here to decrease wavegraph amplitude by 1dB - + Нажмите здесь, чтобы снизить амплитуду графа волны на 1дБ Stereomode Maximum @@ -7048,7 +7082,7 @@ Please make sure you have read-permission to the file and the directory containi Process based on the maximum of both stereo channels - + Процесс основанный на максимуме от обоих каналов Stereomode Average @@ -7056,7 +7090,7 @@ Please make sure you have read-permission to the file and the directory containi Process based on the average of both stereo channels - + Процесс основанный на средней обоих каналов Stereomode Unlinked @@ -7064,7 +7098,7 @@ Please make sure you have read-permission to the file and the directory containi Process each stereo channel independently - + Обрабатывает каждый стерео канал независимо @@ -7227,7 +7261,7 @@ 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. - В этом окне показана информация обо всех модулях LADSPA, которые обнаружила LMMS. Они разделены на пять категорий, в зависимости от названий и типов портов. + В этом окне показана информация обо всех модулях LADSPA, которые обнаружила LMMS. Они разделены на пять категорий, в зависимости от названий и типов портов. Доступные эффекты — это те, которые могут быть использоаны в LMMS. Чтобы эффект LADSPA мог быть использован, он должен, во-первых, быть собственно эффектом, т. е. иметь как входные так и выходные каналы. LMMS в качестве входного канала воспринимает аудиопорт, содержащий в названии „in“, а выходные узнаёт по подстроке „out“. Для использования в LMMS число входных каналов должно совпадать с числом выходных, и эффект должен иметь возможность использования в реальном времени. @@ -7239,7 +7273,7 @@ Double clicking any of the plugins will bring up information on the ports. +Двойной щелчок левой кнопкой мыши по модулю даст информацию о его портах. Type: @@ -7472,7 +7506,7 @@ Double clicking any of the plugins will bring up information on the ports. Click here for bandlimited saw wave. - + Нажать здесь для пилообразной волны с ограниченной полосой. Bandlimited square wave @@ -7480,7 +7514,7 @@ Double clicking any of the plugins will bring up information on the ports. Click here for bandlimited square wave. - + Нажать здесь для квадратной волны с ограниченной полосой. Bandlimited triangle wave @@ -7488,7 +7522,7 @@ Double clicking any of the plugins will bring up information on the ports. Click here for bandlimited triangle wave. - + Нажать здесь для треуголной волны с ограниченной полосой. Bandlimited moog saw wave @@ -7496,7 +7530,7 @@ Double clicking any of the plugins will bring up information on the ports. Click here for bandlimited moog saw wave. - + Нажать здесь для пилообразной муг (moog) волны с ограниченной полосой. @@ -8091,23 +8125,23 @@ Double clicking any of the plugins will bring up information on the ports. 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 - + Осц %1 стерео расстройка Osc %1 harmonic: - + Осц %1 гармоника: @@ -8237,11 +8271,11 @@ Double clicking any of the plugins will bring up information on the ports. Length of each step in sweep: - Длина каждого шага в развёртке: + Длина каждого такта в развёртке: Length of each step in sweep - Длина каждого шага в развёртке + Длина каждого такта в развёртке Wave pattern duty @@ -8369,7 +8403,7 @@ Double clicking any of the plugins will bring up information on the ports. The delay between step change - Задержка между изменениями шага + Задержка между изменениями такта Draw the wave here @@ -8470,19 +8504,19 @@ This chip was used in the Commodore 64 computer. 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 @@ -8490,11 +8524,11 @@ This chip was used in the Commodore 64 computer. plugin for waveshaping - + Плагин для сглаживания волн Boost your bass the fast and simple way - + Накачай свой бас быстро и просто Versatile drum synthesizer @@ -8546,7 +8580,7 @@ This chip was used in the Commodore 64 computer. A native eq plugin - + Родной плагин эквалайзера A 4-band Crossover Equalizer @@ -8568,12 +8602,12 @@ This chip was used in the Commodore 64 computer. - PulseAudio (bad latency!) - + PulseAudio + PulseAudio (большая задержка!) Dummy (no MIDI support) - + Dummy (без поддержки MIDI) ALSA Raw-MIDI (Advanced Linux Sound Architecture) @@ -8585,7 +8619,7 @@ This chip was used in the Commodore 64 computer. Dummy (no sound output) - + Dummy (без вывода звука) ALSA (Advanced Linux Sound Architecture) @@ -8660,7 +8694,7 @@ This chip was used in the Commodore 64 computer. A soundfont %1 could not be loaded. - + Soundfont %1 не удаётся загрузить. @@ -9283,19 +9317,19 @@ The LED in the lower right corner of the waveform editor determines whether the waveShaperControlDialog INPUT - + ВХОД Input gain: - + Входная мощность: OUTPUT - + Выход Output gain: - + Выходная мощность: Reset waveform @@ -9303,7 +9337,7 @@ The LED in the lower right corner of the waveform editor determines whether the Click here to reset the wavegraph back to default - + Сбросить граф волны обратно по умолчанию Smooth waveform @@ -9311,7 +9345,7 @@ The LED in the lower right corner of the waveform editor determines whether the Click here to apply smoothing to wavegraph - + Применить сглаживание к графу волны Increase graph amplitude by 1dB @@ -9319,7 +9353,7 @@ The LED in the lower right corner of the waveform editor determines whether the Click here to increase wavegraph amplitude by 1dB - + Повыситьить амплитуду графа волны на 1дБ Decrease graph amplitude by 1dB @@ -9327,7 +9361,7 @@ The LED in the lower right corner of the waveform editor determines whether the Click here to decrease wavegraph amplitude by 1dB - + Снизить амплитуду графа волны на 1дБ Clip input @@ -9335,18 +9369,18 @@ The LED in the lower right corner of the waveform editor determines whether the Clip input signal to 0dB - + Срезать входной сигнал до 0дБ waveShaperControls Input gain - + Входная мощность Output gain - + Выходная мощность diff --git a/data/locale/sv.ts b/data/locale/sv.ts index 6f57e6f6f..632307fa6 100644 --- a/data/locale/sv.ts +++ b/data/locale/sv.ts @@ -5,27 +5,27 @@ AboutDialog About LMMS - + Om LMMS Version %1 (%2/%3, Qt %4, %5) - + Version %1 (%2/%3, Qt %4, %5) About - Om + Om LMMS - easy music production for everyone - + LMMS - enkel musikproduktion för alla Authors - + Medverkande Translation - + Översättning Current language not translated (or native English). @@ -35,11 +35,11 @@ If you're interested in translating LMMS in another language or want to imp License - + Licens Copyright (c) 2004-2014, LMMS developers - + Copyright (c) 2004-2014, LMMS utvecklare <html><head/><body><p><a href="http://lmms.io"><span style=" text-decoration: underline; color:#0000ff;">http://lmms.io</span></a></p></body></html> @@ -47,26 +47,26 @@ If you're interested in translating LMMS in another language or want to imp LMMS - + LMMS Involved - + Involverad Contributors ordered by number of commits: - + Medverkande, ordnade efter mängd bidrag: AmplifierControlDialog VOL - VOL + VOL Volume: - Volym: + Volym: PAN @@ -78,26 +78,26 @@ If you're interested in translating LMMS in another language or want to imp LEFT - + VÄNSTER Left gain: - + Vänster förstärkning: RIGHT - + HÖGER Right gain: - + Höger förstärkning: AmplifierControls Volume - Volym + Volym Panning @@ -105,398 +105,398 @@ If you're interested in translating LMMS in another language or want to imp Left gain - + Vänster förstärkning Right gain - + Höger förstärkning AudioAlsa::setupWidget DEVICE - ENHET + ENHET CHANNELS - KANALER + KANALER AudioFileProcessorView Open other sample - + Oppna 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: + 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: + 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) Disable loop - + Avaktivera looping 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 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å. 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. 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: With this knob you can set the point where the loop starts. - + Den här vreden ställer in vart loopen startar. AudioFileProcessorWaveView Sample length: - + Ljudfilens längd: AudioJack JACK client restarted - + JACK klienten omstartades 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. 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ängde av 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 + KLIENT-NAMN CHANNELS - KANALER + KANALER AudioOss::setupWidget DEVICE - ENHET + ENHET CHANNELS - KANALER + KANALER AudioPortAudio::setupWidget BACKEND - + BACKEND DEVICE - ENHET + ENHET AudioPulseAudio::setupWidget DEVICE - ENHET + ENHET CHANNELS - KANALER + KANALER AudioSdl::setupWidget DEVICE - ENHET + ENHET AutomatableModel &Reset (%1%2) - &Nollställ (%1%2) + &Nollställ (%1%2) &Copy value (%1%2) - + Kopiera värde (%1%2) &Paste value (%1%2) - &Klistra in värde (%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... Remove song-global automation - + Ta bort global automation Remove all linked controls - + Ta bort alla kopplade kontroller AutomationEditor Please open an automation pattern with the context menu of a control! - + Öppna ett automationsmönster ifrån en kontrollers kontextmeny! Values copied - Värden kopierade + Värden kopierade All selected values were copied to the clipboard. - Alla valda värden blev kopierade till urklipp. + Alla valda värden blev kopierade till urklipp. AutomationEditorWindow Play/pause current pattern (Space) - Spela/pausa aktuellt mönster (mellanslag) + 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. - + Clicka här för att spela det aktuella mönstret. Det här är hjälpsamt när man redigerar. Mönstret spelas från början igen när de 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 (Ctrl+X) - klipp ut valda värden (ctrl+X) + Klipp ut valda värden (Ctrl+X) Copy selected values (Ctrl+C) - Kopiera valda värden (ctrl+C) + Kopiera valda värden (ctrl+C) Paste values from clipboard Ctrl+V) - + Klistra värden (Ctrl+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 AutomationPattern Drag a control while pressing <Ctrl> - + Dra en kontroll samtidigt som du håller <Ctrl> Model is already connected to this pattern. - + Modellen är redan kopplad till detta mönstret. 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 + Nollställ namn Change name - Byt namn + Byt namn %1 Connections - + %1 Kopplingar Disconnect "%1" - + Avkoppla "%1" Set/clear record @@ -504,152 +504,152 @@ If you're interested in translating LMMS in another language or want to imp Flip Vertically (Visible) - + Spegla Vertikalt (Synligt) Flip Horizontally (Visible) - + Spegla Horizontellt (Synligt) AutomationTrack Automation track - + Automationsspår BBEditor Beat+Bassline Editor - + Redigera Trummor+Bas Play/pause current beat/bassline (Space) - + Spela/pause Trummor+Bas Stop playback of current beat/bassline (Space) - + Avsluta uppspelning av trummor/bas 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. 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 BBTCOView Open in Beat+Bassline-Editor - + Redigera Trummor+Bas Reset name - Nollställ namn + Nollställ namn Change name - Byt namn + Byt namn Change color - Byt färg + Byt färg Reset color to default - + Byt färg till standard BBTrack Beat/Bassline %1 - + Trum/Basmönster %1 Clone of %1 - + Kopia av %1 BassBoosterControlDialog FREQ - + FREQ Frequency: - + Frekvens: GAIN - + FÖRST Gain: - + Förstärkning: RATIO - + RATIO Ratio: - + Ratio: BassBoosterControls Frequency - + Frekvens Gain - + Förstärkning Ratio - + Ratio BitcrushControlDialog IN - + IN OUT - + UT GAIN - + FÖRST Input Gain: - + Input Förstärkning: NOIS @@ -661,7 +661,7 @@ If you're interested in translating LMMS in another language or want to imp Output Gain: - + Output Förstärkning CLIP @@ -685,11 +685,11 @@ If you're interested in translating LMMS in another language or want to imp Depth - + Djup Depth Enabled - + Djup aktiverat Enable bitdepth-crushing @@ -709,22 +709,22 @@ If you're interested in translating LMMS in another language or want to imp Levels - + Nivåer Levels: - + Nivåer: CaptionMenu &Help - &Hjälp + &Hjälp Help (not available) - + Hjälp (inte tillgängligt) @@ -742,38 +742,38 @@ If you're interested in translating LMMS in another language or want to imp Controller Controller %1 - + Kontroller %1 ControllerConnectionDialog Connection Settings - + Kopplingsinställningar MIDI CONTROLLER - + MIDI KONTROLLER Input channel - + Inputkanal CHANNEL - KANAL + KANAL Input controller - + Inputkontroller CONTROLLER - + KONTROLLER Auto Detect - + Upptäck Automatiskt MIDI-devices to receive MIDI-events from @@ -781,7 +781,7 @@ If you're interested in translating LMMS in another language or want to imp USER CONTROLLER - + ANVÄNDARKONTROLLER MAPPING FUNCTION @@ -789,15 +789,15 @@ If you're interested in translating LMMS in another language or want to imp OK - + OK Cancel - Avbryt + Avbryt LMMS - + LMMS Cycle Detected. @@ -812,38 +812,38 @@ If you're interested in translating LMMS in another language or want to imp Add - Lägg till + Lägg till Confirm Delete - + Bekräfta Borttagning Confirm delete? There are existing connection(s) associted 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. ControllerView Controls - Kontroller + 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 &Remove this plugin - &Ta bort denna pluginen + @@ -1124,7 +1124,7 @@ If you're interested in translating LMMS in another language or want to imp DummyEffect NOT FOUND - + HITTAS INTE @@ -1468,7 +1468,7 @@ Right clicking will bring up a context menu where you can change the order in wh Click here for a user-defined wave. Afterwards, drag an according sample-file onto the LFO graph. - + Klicka här för att använda en annan vågform. Dra sedan en ljudfil till LFO grafen FREQ x 100 @@ -1504,7 +1504,7 @@ Right clicking will bring up a context menu where you can change the order in wh 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. @@ -1958,11 +1958,11 @@ Please make sure you have write-permission to the file and the directory contain Loading sample - + Laddar ljudfil Please wait, loading sample for preview... - + Ljudfilen laddas för förhandsvisning... --- Factory files --- @@ -3550,7 +3550,11 @@ Please visit http://lmms.sf.net/wiki for documentation on LMMS. - LMMS Project (*.mmpz *.mmp);;LMMS Project Template (*.mpt) + LMMS Project + + + + LMMS Project Template @@ -3559,19 +3563,19 @@ Please visit http://lmms.sf.net/wiki for documentation on LMMS. My Samples - + Mina Ljudfiler My Presets - + Mina Presets My Home - + Mit Hem My Computer - + Min Dator Root Directory @@ -3579,15 +3583,15 @@ Please visit http://lmms.sf.net/wiki for documentation on LMMS. &File - + &Fil &Recently Opened Projects - + &Nyligen Öppnade Project Save as New &Version - + Spara som ny &Version E&xport Tracks... @@ -3599,15 +3603,15 @@ Please visit http://lmms.sf.net/wiki for documentation on LMMS. What's This? - + Vad är det här? Open Project - + Öppna Project Save Project - + SparaProject @@ -5323,7 +5327,7 @@ Reason: "%2" SampleTrack Sample track - + Ljudfil spår Volume @@ -5748,7 +5752,7 @@ Latency: %2 ms Add sample-track - + Lägg til ljudfil-spår Add automation-track @@ -6143,7 +6147,7 @@ Se till att du har läsningsrättigheter för filen och katalogen som innehålle - With this knob you can set the coarse detuning of oscillator %1. You can detune the oscillator 12 semitones (1 octave) up and down. This is useful for creating sounds with a chord. + 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. @@ -6621,7 +6625,7 @@ Se till att du har läsningsrättigheter för filen och katalogen som innehålle Click to load a waveform from a sample file - + Klicka för att ladda in en vågform från en ljudfil Phase left @@ -6802,7 +6806,7 @@ Se till att du har läsningsrättigheter för filen och katalogen som innehålle audioFileProcessor Reverse sample - + Spela baklänges Amplify @@ -6810,11 +6814,11 @@ Se till att du har läsningsrättigheter för filen och katalogen som innehålle Start of sample - + Start på ljudfil End of sample - + Slut på ljudfil Stutter @@ -6846,21 +6850,21 @@ Se till att du har läsningsrättigheter för filen och katalogen som innehålle Sample not found: %1 - + Ljudfil hittades inte: %1 bitInvader Samplelength - + Ljudfilslängd bitInvaderView Sample Length - + Ljudfilens längd Sine wave @@ -6868,7 +6872,7 @@ Se till att du har läsningsrättigheter för filen och katalogen som innehålle Triangle wave - triganelvåg + Triganelvåg Saw wave @@ -8505,7 +8509,7 @@ This chip was used in the Commodore 64 computer. - PulseAudio (bad latency!) + PulseAudio diff --git a/data/locale/zh.ts b/data/locale/zh.ts index 48e18d2bf..07c696fb2 100644 --- a/data/locale/zh.ts +++ b/data/locale/zh.ts @@ -3557,8 +3557,12 @@ Please visit http://lmms.sf.net/wiki for documentation on LMMS. 重做 - LMMS Project (*.mmpz *.mmp);;LMMS Project Template (*.mpt) - LMMS 工程 (*.mmpz *.mmp);;LMMS 工程模板 (*.mpt) + LMMS Project + LMMS 工程 + + + LMMS Project Template + LMMS 工程模板 Volumes @@ -6155,7 +6159,7 @@ Please make sure you have read-permission to the file and the directory containi - With this knob you can set the coarse detuning of oscillator %1. You can detune the oscillator 12 semitones (1 octave) up and down. This is useful for creating sounds with a chord. + 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. @@ -8517,7 +8521,7 @@ This chip was used in the Commodore 64 computer. - PulseAudio (bad latency!) + PulseAudio diff --git a/data/themes/default/main_toolbar_bg.png b/data/themes/default/main_toolbar_bg.png deleted file mode 100644 index d6e662ab3..000000000 Binary files a/data/themes/default/main_toolbar_bg.png and /dev/null differ diff --git a/data/themes/default/step_btn_duplicate.png b/data/themes/default/step_btn_duplicate.png new file mode 100644 index 000000000..af9521fad Binary files /dev/null and b/data/themes/default/step_btn_duplicate.png differ diff --git a/data/themes/default/toolbar_bg.png b/data/themes/default/toolbar_bg.png deleted file mode 100644 index bbe26abf3..000000000 Binary files a/data/themes/default/toolbar_bg.png and /dev/null differ diff --git a/include/AudioJack.h b/include/AudioJack.h index 32f658399..35801ef03 100644 --- a/include/AudioJack.h +++ b/include/AudioJack.h @@ -97,8 +97,6 @@ private: bool m_active; bool m_stopped; - QSemaphore m_stopSemaphore; - QVector m_outputPorts; jack_default_audio_sample_t * * m_tempOutBufs; surroundSampleFrame * m_outBuf; diff --git a/include/AudioPulseAudio.h b/include/AudioPulseAudio.h index f8893733c..5a8504d1f 100644 --- a/include/AudioPulseAudio.h +++ b/include/AudioPulseAudio.h @@ -46,7 +46,7 @@ public: inline static QString name() { - return QT_TRANSLATE_NOOP( "setupWidget", "PulseAudio (bad latency!)" ); + return QT_TRANSLATE_NOOP( "setupWidget", "PulseAudio" ); } static QString probeDevice(); diff --git a/include/BBEditor.h b/include/BBEditor.h index aea2f8763..17ab510ab 100644 --- a/include/BBEditor.h +++ b/include/BBEditor.h @@ -82,6 +82,7 @@ public: public slots: void addSteps(); + void cloneSteps(); void removeSteps(); void addAutomationTrack(); @@ -91,6 +92,7 @@ protected slots: private: BBTrackContainer * m_bbtc; + void makeSteps( bool clone ); }; diff --git a/include/ConfigManager.h b/include/ConfigManager.h index ecb6815ce..12668e8a1 100644 --- a/include/ConfigManager.h +++ b/include/ConfigManager.h @@ -35,6 +35,7 @@ #include "export.h" #include "MemoryManager.h" +#include "lmmsversion.h" class Engine; @@ -100,6 +101,11 @@ public: return dataDir() + SAMPLES_PATH; } + QString defaultVersion() const + { + return LMMS_VERSION; + } + QString defaultArtworkDir() const { return m_dataDir + DEFAULT_THEME_PATH; @@ -135,9 +141,14 @@ public: return m_ladDir; } - const QString & recoveryFile() const + const QString recoveryFile() const { - return m_recoveryFile; + return m_workingDir + "recover.mmp"; + } + + const QString & version() const + { + return m_version; } #ifdef LMMS_HAVE_STK @@ -180,6 +191,7 @@ public: void setArtworkDir( const QString & _ad ); void setFLDir( const QString & _fd ); 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 ); @@ -192,6 +204,8 @@ private: ConfigManager( const ConfigManager & _c ); ~ConfigManager(); + + void upgrade(); const QString m_lmmsRcFile; QString m_workingDir; @@ -200,7 +214,7 @@ private: QString m_vstDir; QString m_flDir; QString m_ladDir; - QString m_recoveryFile; + QString m_version; #ifdef LMMS_HAVE_STK QString m_stkDir; #endif diff --git a/include/DataFile.h b/include/DataFile.h index 1d5f71f78..c8586fd9d 100644 --- a/include/DataFile.h +++ b/include/DataFile.h @@ -58,6 +58,12 @@ public: virtual ~DataFile(); + /// + /// \brief validate + /// performs basic validation, compared to file extension. + /// + bool validate( QString extension ); + QString nameWithExtension( const QString& fn ) const; void write( QTextStream& strm ); diff --git a/include/ExportFilter.h b/include/ExportFilter.h new file mode 100644 index 000000000..857ed1b6c --- /dev/null +++ b/include/ExportFilter.h @@ -0,0 +1,64 @@ +/* + * ExportFilter.h - declaration of class ExportFilter, the base-class for all + * file export filters + * + * Copyright (c) 2006-2014 Tobias Doerffel + * + * This file is part of LMMS - http://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 EXPORT_FILTER_H +#define EXPORT_FILTER_H + +#include + +#include "TrackContainer.h" +#include "Plugin.h" + + +class EXPORT ExportFilter : public Plugin +{ +public: + ExportFilter( const Descriptor * _descriptor ) : Plugin( _descriptor, NULL ) {} + virtual ~ExportFilter() {} + + + virtual bool tryExport( const TrackContainer::TrackList &tracks, int tempo, const QString &filename ) = 0; +protected: + + virtual void saveSettings( QDomDocument &, QDomElement & ) + { + } + + virtual void loadSettings( const QDomElement & ) + { + } + + virtual QString nodeName() const + { + return "import_filter"; + } + + +private: + +} ; + + +#endif diff --git a/include/FadeButton.h b/include/FadeButton.h index 6e7371f9f..4f05b3491 100644 --- a/include/FadeButton.h +++ b/include/FadeButton.h @@ -39,6 +39,7 @@ public: _activated_color, QWidget * _parent ); virtual ~FadeButton(); + void setActiveColor( const QColor & activated_color ); public slots: diff --git a/include/InstrumentTrack.h b/include/InstrumentTrack.h index 16536c081..8c8c963fa 100644 --- a/include/InstrumentTrack.h +++ b/include/InstrumentTrack.h @@ -306,6 +306,9 @@ public: static void cleanupWindowCache(); + // Create a menu for assigning/creating channels for this track + QMenu * createFxMenu( QString title, QString newFxLabel ); + protected: virtual void dragEnterEvent( QDragEnterEvent * _dee ); @@ -320,6 +323,10 @@ private slots: void midiInSelected(); void midiOutSelected(); void midiConfigChanged(); + void muteChanged(); + + void assignFxLine( int channelIndex ); + void createFxLine(); private: @@ -374,6 +381,12 @@ public: void setInstrumentTrackView( InstrumentTrackView * _tv ); + InstrumentTrackView *instrumentTrackView() + { + return m_itv; + } + + PianoView * pianoView() { return m_pianoView; diff --git a/include/MainWindow.h b/include/MainWindow.h index 82f3cd365..5e1f294ae 100644 --- a/include/MainWindow.h +++ b/include/MainWindow.h @@ -69,10 +69,12 @@ public: /// opens another file...) must call this before and may only proceed if /// this function returns true. /// + /// \param stopPlayback whether playback should be stopped upon prompting. If set to false, the caller should ensure that Engine::getSong()->stop() is called before unloading/loading a song. + /// /// \return true if the user allows the software to proceed, false if they /// cancel the action. /// - bool mayChangeProject(); + bool mayChangeProject(bool stopPlayback); void clearKeyModifiers(); @@ -172,6 +174,7 @@ private: friend class GuiApplication; + QMenu * m_viewMenu; private slots: void browseHelp(); @@ -179,6 +182,8 @@ private slots: void openRecentlyOpenedProject( QAction * _action ); void showTool( QAction * _idx ); void updateRecentlyOpenedProjectsMenu(); + void updateViewMenu( void ); + void updateConfig( QAction * _who ); void autoSave(); diff --git a/include/Note.h b/include/Note.h index d5cc0363e..62a6f6f93 100644 --- a/include/Note.h +++ b/include/Note.h @@ -81,36 +81,37 @@ const float MaxDetuning = 4 * 12.0f; class EXPORT Note : public SerializingObject { public: - Note( const MidiTime & _length = MidiTime( 0 ), - const MidiTime & _pos = MidiTime( 0 ), + Note( const MidiTime & length = MidiTime( 0 ), + const MidiTime & pos = MidiTime( 0 ), int key = DefaultKey, - volume_t _volume = DefaultVolume, - panning_t _panning = DefaultPanning, - DetuningHelper * _detuning = NULL ); - Note( const Note & _note ); + volume_t volume = DefaultVolume, + panning_t panning = DefaultPanning, + DetuningHelper * detuning = NULL ); + Note( const Note & note ); virtual ~Note(); // used by GUI - inline void setSelected( const bool _selected ) { m_selected = _selected; } - inline void setOldKey( const int _oldKey ) { m_oldKey = _oldKey; } - inline void setOldPos( const MidiTime & _oldPos ) { m_oldPos = _oldPos; } - inline void setOldLength( const MidiTime & _oldLength ) + inline void setSelected( const bool selected ) { m_selected = selected; } + inline void setOldKey( const int oldKey ) { m_oldKey = oldKey; } + inline void setOldPos( const MidiTime & oldPos ) { m_oldPos = oldPos; } + + inline void setOldLength( const MidiTime & oldLength ) { - m_oldLength = _oldLength; + m_oldLength = oldLength; } - inline void setIsPlaying( const bool _isPlaying ) + inline void setIsPlaying( const bool isPlaying ) { - m_isPlaying = _isPlaying; + m_isPlaying = isPlaying; } - void setLength( const MidiTime & _length ); - void setPos( const MidiTime & _pos ); - void setKey( const int _key ); + void setLength( const MidiTime & length ); + void setPos( const MidiTime & pos ); + void setKey( const int key ); virtual void setVolume( volume_t volume ); virtual void setPanning( panning_t panning ); - void quantizeLength( const int _q_grid ); - void quantizePos( const int _q_grid ); + void quantizeLength( const int qGrid ); + void quantizePos( const int qGrid ); static inline bool lessThan( Note * &lhs, Note * &rhs ) { @@ -160,9 +161,9 @@ public: return m_pos; } - inline MidiTime pos( MidiTime _base_pos ) const + inline MidiTime pos( MidiTime basePos ) const { - const int bp = _base_pos; + const int bp = basePos; return m_pos - bp; } @@ -196,20 +197,20 @@ public: return classNodeName(); } - static MidiTime quantized( const MidiTime & _m, const int _q_grid ); + static MidiTime quantized( const MidiTime & m, const int qGrid ); DetuningHelper * detuning() const { return m_detuning; } bool hasDetuningInfo() const; + bool withinRange(int tickStart, int tickEnd) const; void createDetuning(); protected: - virtual void saveSettings( QDomDocument & _doc, - QDomElement & _parent ); + virtual void saveSettings( QDomDocument & doc, QDomElement & parent ); virtual void loadSettings( const QDomElement & _this ); @@ -234,4 +235,3 @@ typedef QVector NoteVector; #endif - diff --git a/include/Pattern.h b/include/Pattern.h index 511dd6cd3..ce6702fbb 100644 --- a/include/Pattern.h +++ b/include/Pattern.h @@ -127,6 +127,7 @@ protected: protected slots: void addSteps(); + void cloneSteps(); void removeSteps(); void clear(); void changeTimeSignature(); @@ -179,8 +180,8 @@ protected slots: protected: virtual void constructContextMenu( QMenu * ); - virtual void mouseDoubleClickEvent( QMouseEvent * _me ); virtual void mousePressEvent( QMouseEvent * _me ); + virtual void mouseDoubleClickEvent( QMouseEvent * _me ); virtual void paintEvent( QPaintEvent * _pe ); virtual void resizeEvent( QResizeEvent * _re ) { diff --git a/include/Plugin.h b/include/Plugin.h index 0b207a584..a182acea1 100644 --- a/include/Plugin.h +++ b/include/Plugin.h @@ -85,19 +85,19 @@ public: { typedef QMap AttributeMap; - inline Key( const Plugin::Descriptor * _desc = NULL, - const QString & _name = QString(), - const AttributeMap & _am = AttributeMap() ) + inline Key( const Plugin::Descriptor * desc = NULL, + const QString & name = QString(), + const AttributeMap & am = AttributeMap() ) : - desc( _desc ), - name( _name ), - attributes( _am ) + desc( desc ), + name( name ), + attributes( am ) { } - Key( const QDomElement & _key ); + Key( const QDomElement & key ); - QDomElement saveXML( QDomDocument & _doc ) const; + QDomElement saveXML( QDomDocument & doc ) const; inline bool isValid() const { @@ -134,22 +134,22 @@ public: const Plugin::PluginTypes m_type; } ; - SubPluginFeatures *subPluginFeatures; + SubPluginFeatures * subPluginFeatures; } ; // 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 ); + Plugin( const Descriptor * descriptor, Model * parent ); virtual ~Plugin(); // returns display-name out of descriptor virtual QString displayName() const { return Model::displayName().isEmpty() - ? m_descriptor->displayName - : Model::displayName(); + ? m_descriptor->displayName + : Model::displayName(); } // return plugin-type @@ -159,38 +159,38 @@ public: } // return plugin-descriptor for further information - inline const Descriptor* descriptor() const + 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 - virtual void loadFile( const QString& file ); + 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. - virtual AutomatableModel* childModel( const QString& modelName ); + 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 ); + static Plugin * instantiate( const QString& pluginName, Model * parent, void * data ); // create a view for the model - PluginView* createView( QWidget* parent ); + PluginView * createView( QWidget * parent ); protected: // create a view for the model - virtual PluginView* instantiateView( QWidget* ) = 0; - void collectErrorForUI( QString err_msg ); + virtual PluginView* instantiateView( QWidget * ) = 0; + void collectErrorForUI( QString errMsg ); private: - const Descriptor* m_descriptor; + const Descriptor * m_descriptor; // pointer to instantiation-function in plugin - typedef Plugin * ( * InstantiationHook )( Model*, void* ); + typedef Plugin * ( * InstantiationHook )( Model * , void * ); } ; diff --git a/include/PresetPreviewPlayHandle.h b/include/PresetPreviewPlayHandle.h index 6dd8c8e19..0ebed9c89 100644 --- a/include/PresetPreviewPlayHandle.h +++ b/include/PresetPreviewPlayHandle.h @@ -35,7 +35,7 @@ class PreviewTrackContainer; class EXPORT PresetPreviewPlayHandle : public PlayHandle { public: - PresetPreviewPlayHandle( const QString& presetFile, bool loadByPlugin = false ); + PresetPreviewPlayHandle( const QString& presetFile, bool loadByPlugin = false, DataFile *dataFile = 0 ); virtual ~PresetPreviewPlayHandle(); virtual void play( sampleFrame* buffer ); diff --git a/include/ProjectVersion.h b/include/ProjectVersion.h index 37cc83565..545b91668 100644 --- a/include/ProjectVersion.h +++ b/include/ProjectVersion.h @@ -61,7 +61,6 @@ private: CompareType m_compareType; } ; - /* * ProjectVersion v. ProjectVersion */ @@ -72,5 +71,4 @@ inline bool operator>=(const ProjectVersion & v1, const ProjectVersion & v2) { r inline bool operator==(const ProjectVersion & v1, const ProjectVersion & v2) { return ProjectVersion::compare(v1, v2) == 0; } inline bool operator!=(const ProjectVersion & v1, const ProjectVersion & v2) { return ProjectVersion::compare(v1, v2) != 0; } - #endif diff --git a/include/RemotePlugin.h b/include/RemotePlugin.h index d57a5d293..42caa36aa 100644 --- a/include/RemotePlugin.h +++ b/include/RemotePlugin.h @@ -36,17 +36,12 @@ #include #include -#ifdef LMMS_BUILD_WIN32 + +#if defined(LMMS_HAVE_SYS_IPC_H) && defined(LMMS_HAVE_SEMAPHORE_H) +#include +#include +#else #define USE_QT_SEMAPHORES -#define USE_QT_SHMEM -#endif - -#ifdef LMMS_BUILD_APPLE -#define USE_QT_SEMAPHORES -#endif - - -#ifdef USE_QT_SEMAPHORES #ifdef LMMS_HAVE_PROCESS_H #include @@ -54,39 +49,25 @@ #include #include - -#else /* USE_QT_SEMAPHORES */ - -#ifdef LMMS_HAVE_SYS_IPC_H -#include #endif -#ifdef LMMS_HAVE_SEMAPHORE_H -#include -#endif - -#endif - - -#ifdef USE_QT_SHMEM - -#include -#include - -typedef int32_t key_t; - -#else /* USE_QT_SHMEM */ #ifdef LMMS_HAVE_SYS_SHM_H #include -#endif #ifdef LMMS_HAVE_UNISTD_H #include #endif +#else +#define USE_QT_SHMEM +#include +#include + +#if !defined(LMMS_HAVE_SYS_TYPES_H) || defined(LMMS_BUILD_WIN32) +typedef int32_t key_t; +#endif #endif - #ifdef LMMS_HAVE_LOCALE_H diff --git a/include/Song.h b/include/Song.h index 5da09818a..053e16345 100644 --- a/include/Song.h +++ b/include/Song.h @@ -49,10 +49,9 @@ const tick_t MaxSongLength = 9999 * DefaultTicksPerTact; class EXPORT Song : public TrackContainer { Q_OBJECT - mapPropertyFromModel(int,getTempo,setTempo,m_tempoModel); - mapPropertyFromModel(int,masterPitch,setMasterPitch,m_masterPitchModel); - mapPropertyFromModel(int,masterVolume,setMasterVolume, - m_masterVolumeModel); + mapPropertyFromModel( int,getTempo,setTempo,m_tempoModel ); + mapPropertyFromModel( int,masterPitch,setMasterPitch,m_masterPitchModel ); + mapPropertyFromModel( int,masterVolume,setMasterVolume, m_masterVolumeModel ); public: enum PlayModes { @@ -70,19 +69,19 @@ public: bool hasErrors(); QString* errorSummary(); - class playPos : public MidiTime + class PlayPos : public MidiTime { public: - playPos( const int _abs = 0 ) : - MidiTime( _abs ), + PlayPos( const int abs = 0 ) : + MidiTime( abs ), m_timeLine( NULL ), m_timeLineUpdate( true ), m_currentFrame( 0.0f ) { } - inline void setCurrentFrame( const float _f ) + inline void setCurrentFrame( const float f ) { - m_currentFrame = _f; + m_currentFrame = f; } inline float currentFrame() const { @@ -104,9 +103,9 @@ public: { return m_elapsedMilliSeconds; } - inline void setMilliSeconds( float _ellapsedMilliSeconds ) + inline void setMilliSeconds( float ellapsedMilliSeconds ) { - m_elapsedMilliSeconds = (_ellapsedMilliSeconds); + m_elapsedMilliSeconds = ellapsedMilliSeconds; } inline int getTacts() const { @@ -123,14 +122,14 @@ public: // Returns the beat position inside the bar, 0-based inline int getBeat() const { - return (currentTick() - currentTact()*ticksPerTact()) / - (ticksPerTact() / m_timeSigModel.getNumerator() ); + return ( currentTick() - currentTact() * ticksPerTact() ) / + ( ticksPerTact() / m_timeSigModel.getNumerator() ); } // the remainder after bar and beat are removed inline int getBeatTicks() const { - return (currentTick() - currentTact()*ticksPerTact()) % - (ticksPerTact() / m_timeSigModel.getNumerator() ); + return ( currentTick() - currentTact() * ticksPerTact() ) % + ( ticksPerTact() / m_timeSigModel.getNumerator() ); } inline int getTicks() const { @@ -151,7 +150,7 @@ public: inline bool isPlaying() const { - return m_playing && m_exporting == false; + return m_playing == true && m_exporting == false; } inline bool isStopped() const @@ -186,9 +185,9 @@ public: return m_playMode; } - inline playPos & getPlayPos( PlayModes _pm ) + inline PlayPos & getPlayPos( PlayModes pm ) { - return m_playPos[_pm]; + return m_playPos[pm]; } void updateLength(); @@ -208,11 +207,11 @@ public: // file management void createNewProject(); - void createNewProjectFromTemplate( const QString & _template ); - void loadProject( const QString & _filename ); + void createNewProjectFromTemplate( const QString & templ ); + void loadProject( const QString & filename ); bool guiSaveProject(); - bool guiSaveProjectAs( const QString & _filename ); - bool saveProjectFile( const QString & _filename ); + bool guiSaveProjectAs( const QString & filename ); + bool saveProjectFile( const QString & filename ); const QString & projectFileName() const { @@ -239,8 +238,8 @@ public: return false; } - void addController( Controller * _c ); - void removeController( Controller * _c ); + void addController( Controller * c ); + void removeController( Controller * c ); const ControllerVector & controllers() const @@ -259,15 +258,16 @@ public slots: void playSong(); void record(); void playAndRecord(); - void playTrack( Track * _trackToPlay ); + void playTrack( Track * trackToPlay ); void playBB(); - void playPattern(const Pattern* patternToPlay, bool _loop = true ); + void playPattern( const Pattern * patternToPlay, bool loop = true ); void togglePause(); void stop(); void importProject(); - void exportProject(bool multiExport=false); + void exportProject( bool multiExport = false ); void exportProjectTracks(); + void exportProjectMidi(); void startExport(); void stopExport(); @@ -315,13 +315,14 @@ private: inline f_cnt_t currentFrame() const { - return m_playPos[m_playMode].getTicks() * Engine::framesPerTick() + m_playPos[m_playMode].currentFrame(); + return m_playPos[m_playMode].getTicks() * Engine::framesPerTick() + + m_playPos[m_playMode].currentFrame(); } - void setPlayPos( tick_t _ticks, PlayModes _play_mode ); + void setPlayPos( tick_t ticks, PlayModes playMode ); - void saveControllerStates( QDomDocument & _doc, QDomElement & _this ); - void restoreControllerStates( const QDomElement & _this ); + void saveControllerStates( QDomDocument & doc, QDomElement & element ); + void restoreControllerStates( const QDomElement & element ); AutomationTrack * m_globalAutomationTrack; @@ -351,7 +352,7 @@ private: QList * m_errors; PlayModes m_playMode; - playPos m_playPos[Mode_Count]; + PlayPos m_playPos[Mode_Count]; tact_t m_length; Track * m_trackToPlay; @@ -374,10 +375,9 @@ signals: void projectLoaded(); void playbackStateChanged(); void playbackPositionChanged(); - void lengthChanged( int _tacts ); - void tempoChanged( bpm_t _new_bpm ); - void timeSignatureChanged( int _old_ticks_per_tact, - int _ticks_per_tact ); + void lengthChanged( int tacts ); + void tempoChanged( bpm_t newBPM ); + void timeSignatureChanged( int oldTicksPerTact, int ticksPerTact ); } ; diff --git a/include/TimeLineWidget.h b/include/TimeLineWidget.h index 37e1f6ee7..f962657e6 100644 --- a/include/TimeLineWidget.h +++ b/include/TimeLineWidget.h @@ -62,11 +62,11 @@ public: } ; - TimeLineWidget( int _xoff, int _yoff, float _ppt, Song::playPos & _pos, - const MidiTime & _begin, QWidget * _parent ); + TimeLineWidget( int xoff, int yoff, float ppt, Song::PlayPos & pos, + const MidiTime & begin, QWidget * parent ); virtual ~TimeLineWidget(); - inline Song::playPos & pos() + inline Song::PlayPos & pos() { return( m_pos ); } @@ -169,7 +169,7 @@ private: int m_xOffset; int m_posMarkerX; float m_ppt; - Song::playPos & m_pos; + Song::PlayPos & m_pos; const MidiTime & m_begin; MidiTime m_loopPos[2]; diff --git a/include/Track.h b/include/Track.h index b766b6056..1bebffbf1 100644 --- a/include/Track.h +++ b/include/Track.h @@ -81,7 +81,7 @@ class TrackContentObject : public Model, public JournallingObject mapPropertyFromModel(bool,isMuted,setMuted,m_mutedModel); mapPropertyFromModel(bool,isSolo,setSolo,m_soloModel); public: - TrackContentObject( Track * _track ); + TrackContentObject( Track * track ); virtual ~TrackContentObject(); inline Track * getTrack() const @@ -94,9 +94,9 @@ public: return m_name; } - inline void setName( const QString & _name ) + inline void setName( const QString & name ) { - m_name = _name; + m_name = name; emit dataChanged(); } @@ -122,9 +122,9 @@ public: return m_length; } - inline void setAutoResize( const bool _r ) + inline void setAutoResize( const bool r ) { - m_autoResize = _r; + m_autoResize = r; } inline const bool getAutoResize() const @@ -132,10 +132,10 @@ public: return m_autoResize; } - virtual void movePosition( const MidiTime & _pos ); - virtual void changeLength( const MidiTime & _length ); + virtual void movePosition( const MidiTime & pos ); + virtual void changeLength( const MidiTime & length ); - virtual TrackContentObjectView * createView( TrackView * _tv ) = 0; + virtual TrackContentObjectView * createView( TrackView * tv ) = 0; inline void selectViewOnCreate( bool select ) { @@ -195,7 +195,7 @@ class TrackContentObjectView : public selectableObject, public ModelView Q_PROPERTY( QColor textColor READ textColor WRITE setTextColor ) public: - TrackContentObjectView( TrackContentObject * _tco, TrackView * _tv ); + TrackContentObjectView( TrackContentObject * tco, TrackView * tv ); virtual ~TrackContentObjectView(); bool fixedTCOs(); @@ -207,8 +207,8 @@ public: // qproperty access func QColor fgColor() const; QColor textColor() const; - void setFgColor( const QColor & _c ); - void setTextColor( const QColor & _c ); + void setFgColor( const QColor & c ); + void setTextColor( const QColor & c ); public slots: virtual bool close(); @@ -220,13 +220,13 @@ protected: { } - 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 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 ); float pixelsPerTact(); @@ -276,7 +276,7 @@ private: m_initialMouseGlobalPos = mapToGlobal( pos ); } - bool mouseMovedDistance( QMouseEvent * _me, int distance ); + bool mouseMovedDistance( QMouseEvent * me, int distance ); } ; @@ -293,46 +293,46 @@ class TrackContentWidget : public QWidget, public JournallingObject Q_PROPERTY( QBrush lighterColor READ lighterColor WRITE setLighterColor ) public: - TrackContentWidget( TrackView * _parent ); + TrackContentWidget( TrackView * parent ); virtual ~TrackContentWidget(); /*! \brief Updates the background tile pixmap. */ void updateBackground(); - void addTCOView( TrackContentObjectView * _tcov ); - void removeTCOView( TrackContentObjectView * _tcov ); - void removeTCOView( int _tco_num ) + void addTCOView( TrackContentObjectView * tcov ); + void removeTCOView( TrackContentObjectView * tcov ); + void removeTCOView( int tcoNum ) { - if( _tco_num >= 0 && _tco_num < m_tcoViews.size() ) + if( tcoNum >= 0 && tcoNum < m_tcoViews.size() ) { - removeTCOView( m_tcoViews[_tco_num] ); + removeTCOView( m_tcoViews[tcoNum] ); } } bool canPasteSelection( MidiTime tcoPos, const QMimeData * mimeData ); - bool pasteSelection( MidiTime tcoPos, QDropEvent * _de ); + bool pasteSelection( MidiTime tcoPos, QDropEvent * de ); - MidiTime endPosition( const MidiTime & _pos_start ); + MidiTime endPosition( const MidiTime & posStart ); // qproperty access methods QBrush darkerColor() const; QBrush lighterColor() const; - void setDarkerColor( const QBrush & _c ); - void setLighterColor( const QBrush & _c ); + void setDarkerColor( const QBrush & c ); + void setLighterColor( const QBrush & c ); public slots: void update(); - void changePosition( const MidiTime & _new_pos = MidiTime( -1 ) ); + 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 ); + 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 ); virtual QString nodeName() const { @@ -353,7 +353,7 @@ protected: private: Track * getTrack(); - MidiTime getPosition( int _mouse_x ); + MidiTime getPosition( int mouseX ); TrackView * m_trackView; @@ -375,13 +375,13 @@ class TrackOperationsWidget : public QWidget { Q_OBJECT public: - TrackOperationsWidget( TrackView * _parent ); + TrackOperationsWidget( TrackView * parent ); ~TrackOperationsWidget(); protected: - virtual void mousePressEvent( QMouseEvent * _me ); - virtual void paintEvent( QPaintEvent * _pe ); + virtual void mousePressEvent( QMouseEvent * me ); + virtual void paintEvent( QPaintEvent * pe ); private slots: @@ -391,8 +391,6 @@ private slots: void recordingOn(); void recordingOff(); void clearTrack(); - void assignFxLine( int channelIndex ); - void createFxLine(); private: static QPixmap * s_grip; @@ -407,7 +405,7 @@ private: friend class TrackView; signals: - void trackRemovalScheduled( TrackView * _t ); + void trackRemovalScheduled( TrackView * t ); } ; @@ -437,12 +435,12 @@ public: NumTrackTypes } ; - Track( TrackTypes _type, TrackContainer * _tc ); + Track( TrackTypes type, TrackContainer * tc ); virtual ~Track(); - static Track * create( TrackTypes _tt, TrackContainer * _tc ); - static Track * create( const QDomElement & _this, - TrackContainer * _tc ); + static Track * create( TrackTypes tt, TrackContainer * tc ); + static Track * create( const QDomElement & element, + TrackContainer * tc ); void clone(); @@ -452,20 +450,20 @@ public: return m_type; } - virtual bool play( const MidiTime & _start, const fpp_t _frames, - const f_cnt_t _frame_base, int _tco_num = -1 ) = 0; + virtual bool play( const MidiTime & start, const fpp_t frames, + const f_cnt_t frameBase, int tcoNum = -1 ) = 0; - virtual TrackView * createView( TrackContainerView * _view ) = 0; - virtual TrackContentObject * createTCO( const MidiTime & _pos ) = 0; + virtual TrackView * createView( TrackContainerView * view ) = 0; + virtual TrackContentObject * createTCO( const MidiTime & pos ) = 0; - virtual void saveTrackSpecificSettings( QDomDocument & _doc, - QDomElement & _parent ) = 0; - virtual void loadTrackSpecificSettings( const QDomElement & _this ) = 0; + virtual void saveTrackSpecificSettings( QDomDocument & doc, + QDomElement & parent ) = 0; + virtual void loadTrackSpecificSettings( const QDomElement & element ) = 0; - virtual void saveSettings( QDomDocument & _doc, QDomElement & _this ); - virtual void loadSettings( const QDomElement & _this ); + virtual void saveSettings( QDomDocument & doc, QDomElement & element ); + virtual void loadSettings( const QDomElement & element ); void setSimpleSerializing() { @@ -473,26 +471,26 @@ public: } // -- for usage by TrackContentObject only --------------- - TrackContentObject * addTCO( TrackContentObject * _tco ); - void removeTCO( TrackContentObject * _tco ); + TrackContentObject * addTCO( TrackContentObject * tco ); + void removeTCO( TrackContentObject * tco ); // ------------------------------------------------------- void deleteTCOs(); int numOfTCOs(); - TrackContentObject * getTCO( int _tco_num ); - int getTCONum(const TrackContentObject* _tco ); + TrackContentObject * getTCO( int tcoNum ); + int getTCONum(const TrackContentObject* tco ); const tcoVector & getTCOs() const { - return( m_trackContentObjects ); + return m_trackContentObjects; } - void getTCOsInRange( tcoVector & _tco_v, const MidiTime & _start, - const MidiTime & _end ); - void swapPositionOfTCOs( int _tco_num1, int _tco_num2 ); + void getTCOsInRange( tcoVector & tcoV, const MidiTime & start, + const MidiTime & end ); + void swapPositionOfTCOs( int tcoNum1, int tcoNum2 ); - void insertTact( const MidiTime & _pos ); - void removeTact( const MidiTime & _pos ); + void insertTact( const MidiTime & pos ); + void removeTact( const MidiTime & pos ); tact_t length() const; @@ -505,21 +503,25 @@ public: // name-stuff virtual const QString & name() const { - return( m_name ); + return m_name; } virtual QString displayName() const { - return( name() ); + return name(); } using Model::dataChanged; - inline int getHeight() { - return ( m_height >= MINIMAL_TRACK_HEIGHT ? m_height : DEFAULT_TRACK_HEIGHT ); + inline int getHeight() + { + return m_height >= MINIMAL_TRACK_HEIGHT + ? m_height + : DEFAULT_TRACK_HEIGHT; } - inline void setHeight( int _height ) { - m_height = _height; + inline void setHeight( int height ) + { + m_height = height; } void lock() @@ -536,9 +538,9 @@ public: } public slots: - virtual void setName( const QString & _new_name ) + virtual void setName( const QString & newName ) { - m_name = _new_name; + m_name = newName; emit nameChanged(); } @@ -585,12 +587,12 @@ public: inline const Track * getTrack() const { - return( m_track ); + return m_track; } inline Track * getTrack() { - return( m_track ); + return m_track; } inline TrackContainerView* trackContainerView() @@ -600,22 +602,22 @@ public: inline TrackOperationsWidget * getTrackOperationsWidget() { - return( &m_trackOperationsWidget ); + return &m_trackOperationsWidget; } inline trackSettingsWidget * getTrackSettingsWidget() { - return( &m_trackSettingsWidget ); + return &m_trackSettingsWidget; } inline TrackContentWidget * getTrackContentWidget() { - return( &m_trackContentWidget ); + return &m_trackContentWidget; } bool isMovingTrack() const { - return( m_action == MoveTrack ); + return m_action == MoveTrack; } virtual void update(); @@ -645,13 +647,13 @@ protected: } - 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 ); + 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 ); private: @@ -676,7 +678,7 @@ private: private slots: - void createTCOView( TrackContentObject * _tco ); + void createTCOView( TrackContentObject * tco ); } ; diff --git a/include/lmms_math.h b/include/lmms_math.h index d1a9dcc79..1e3b530ae 100644 --- a/include/lmms_math.h +++ b/include/lmms_math.h @@ -34,7 +34,7 @@ #include using namespace std; -#if defined (LMMS_BUILD_WIN32) || defined (LMMS_BUILD_APPLE) +#if defined (LMMS_BUILD_WIN32) || defined (LMMS_BUILD_APPLE) || defined(LMMS_BUILD_HAIKU) #ifndef isnanf #define isnanf(x) isnan(x) #endif @@ -217,9 +217,11 @@ static inline float logToLinearScale( float min, float max, float value ) { const float mmax = qMax( qAbs( min ), qAbs( max ) ); const float val = value * ( max - min ) + min; - return signedPowf( val / mmax, F_E ) * mmax; + float result = signedPowf( val / mmax, F_E ) * mmax; + return isnan( result ) ? 0 : result; } - return powf( value, F_E ) * ( max - min ) + min; + float result = powf( value, F_E ) * ( max - min ) + min; + return isnan( result ) ? 0 : result; } @@ -231,9 +233,11 @@ static inline float linearToLogScale( float min, float max, float value ) if( min < 0 ) { const float mmax = qMax( qAbs( min ), qAbs( max ) ); - return signedPowf( value / mmax, EXP ) * mmax; + float result = signedPowf( value / mmax, EXP ) * mmax; + return isnan( result ) ? 0 : result; } - return powf( val, EXP ) * ( max - min ) + min; + float result = powf( val, EXP ) * ( max - min ) + min; + return isnan( result ) ? 0 : result; } diff --git a/include/versioninfo.h b/include/versioninfo.h index 9295a56c4..58f7a79e9 100644 --- a/include/versioninfo.h +++ b/include/versioninfo.h @@ -27,3 +27,7 @@ #ifdef LMMS_BUILD_WIN32 #define PLATFORM "win32" #endif + +#ifdef LMMS_BUILD_HAIKU +#define PLATFORM "Haiku" +#endif diff --git a/lmmsconfig.h.in b/lmmsconfig.h.in index d645c5025..496d0db67 100644 --- a/lmmsconfig.h.in +++ b/lmmsconfig.h.in @@ -2,6 +2,7 @@ #cmakedefine LMMS_BUILD_WIN32 #cmakedefine LMMS_BUILD_WIN64 #cmakedefine LMMS_BUILD_APPLE +#cmakedefine LMMS_BUILD_HAIKU #cmakedefine LMMS_HOST_X86 #cmakedefine LMMS_HOST_X86_64 diff --git a/plugins/BassBooster/BassBooster.cpp b/plugins/BassBooster/BassBooster.cpp index d75fa2c66..54fa9e98e 100644 --- a/plugins/BassBooster/BassBooster.cpp +++ b/plugins/BassBooster/BassBooster.cpp @@ -83,18 +83,45 @@ bool BassBoosterEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames if( m_bbControls.m_gainModel.isValueChanged() ) { changeGain(); } if( m_bbControls.m_ratioModel.isValueChanged() ) { changeRatio(); } + float gain = m_bbControls.m_gainModel.value(); + ValueBuffer *gainBuffer = m_bbControls.m_gainModel.valueBuffer(); + int gainInc = gainBuffer ? 1 : 0; + float *gainPtr = gainBuffer ? &( gainBuffer->values()[ 0 ] ) : &gain; + double outSum = 0.0; const float d = dryLevel(); const float w = wetLevel(); - for( fpp_t f = 0; f < frames; ++f ) + if( gainBuffer ) { - outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1]; + //process period using sample exact data + for( fpp_t f = 0; f < frames; ++f ) + { + m_bbFX.leftFX().setGain( *gainPtr ); + m_bbFX.rightFX().setGain( *gainPtr ); + outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1]; - sample_t s[2] = { buf[f][0], buf[f][1] }; - m_bbFX.nextSample( s[0], s[1] ); + sample_t s[2] = { buf[f][0], buf[f][1] }; + m_bbFX.nextSample( s[0], s[1] ); - buf[f][0] = d * buf[f][0] + w * s[0]; - buf[f][1] = d * buf[f][1] + w * s[1]; + buf[f][0] = d * buf[f][0] + w * s[0]; + buf[f][1] = d * buf[f][1] + w * s[1]; + gainPtr += gainInc; + } + } else + { + //process period without sample exact data + m_bbFX.leftFX().setGain( *gainPtr ); + m_bbFX.rightFX().setGain( *gainPtr ); + for( fpp_t f = 0; f < frames; ++f ) + { + outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1]; + + sample_t s[2] = { buf[f][0], buf[f][1] }; + m_bbFX.nextSample( s[0], s[1] ); + + buf[f][0] = d * buf[f][0] + w * s[0]; + buf[f][1] = d * buf[f][1] + w * s[1]; + } } checkGate( outSum / frames ); diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 8de6bb09c..3d1c9f2ee 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -10,7 +10,7 @@ ADD_SUBDIRECTORY(carlabase) ADD_SUBDIRECTORY(carlapatchbay) ADD_SUBDIRECTORY(carlarack) ADD_SUBDIRECTORY(CrossoverEQ) -ADD_SUBDIRECTORY(delay) +ADD_SUBDIRECTORY(Delay) ADD_SUBDIRECTORY(DualFilter) ADD_SUBDIRECTORY(dynamics_processor) ADD_SUBDIRECTORY(Eq) @@ -23,6 +23,7 @@ ADD_SUBDIRECTORY(LadspaEffect) ADD_SUBDIRECTORY(lb302) #ADD_SUBDIRECTORY(lb303) ADD_SUBDIRECTORY(MidiImport) +ADD_SUBDIRECTORY(MidiExport) ADD_SUBDIRECTORY(MultitapEcho) ADD_SUBDIRECTORY(monstro) ADD_SUBDIRECTORY(nes) diff --git a/plugins/Delay/CMakeLists.txt b/plugins/Delay/CMakeLists.txt new file mode 100644 index 000000000..ceb7ceb4a --- /dev/null +++ b/plugins/Delay/CMakeLists.txt @@ -0,0 +1,3 @@ +INCLUDE(BuildPlugin) + +BUILD_PLUGIN(delay DelayEffect.cpp DelayControls.cpp DelayControlsDialog.cpp Lfo.cpp StereoDelay.cpp MOCFILES DelayControls.h DelayControlsDialog.h ../Eq/EqFader.h EMBEDDED_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.png") diff --git a/plugins/delay/delaycontrols.cpp b/plugins/Delay/DelayControls.cpp similarity index 88% rename from plugins/delay/delaycontrols.cpp rename to plugins/Delay/DelayControls.cpp index fd7aaf240..f8241b95e 100644 --- a/plugins/delay/delaycontrols.cpp +++ b/plugins/Delay/DelayControls.cpp @@ -24,8 +24,8 @@ #include -#include "delaycontrols.h" -#include "delayeffect.h" +#include "DelayControls.h" +#include "DelayEffect.h" #include "Engine.h" #include "Song.h" @@ -35,9 +35,12 @@ DelayControls::DelayControls( DelayEffect* effect ): m_delayTimeModel( 0.5, 0.01, 20.0, 0.0001, 20000.0, this, tr( "Delay Samples" )) , m_feedbackModel(0.0f,0.0f,1.0f,0.01f,this,tr( "Feedback" ) ), m_lfoTimeModel(2.0, 0.01, 20.0, 0.0001, 20000.0, this, tr( "Lfo Frequency" ) ), - m_lfoAmountModel(0.0, 0.0, 2.0, 0.0001, 2000.0, this, tr ( "Lfo Amount" ) ) + m_lfoAmountModel(0.0, 0.0, 2.0, 0.0001, 2000.0, this, tr ( "Lfo Amount" ) ), + m_outGainModel( 0.0, -60.0, 20.0, 0.01, this, tr( "Output gain" ) ) { connect( Engine::mixer(), SIGNAL( sampleRateChanged() ), this, SLOT( changeSampleRate() ) ); + m_outPeakL = 0.0; + m_outPeakR = 0.0; } @@ -49,6 +52,7 @@ void DelayControls::loadSettings( const QDomElement &_this ) m_feedbackModel.loadSettings( _this, "FeebackAmount" ); m_lfoTimeModel.loadSettings( _this , "LfoFrequency"); m_lfoAmountModel.loadSettings( _this, "LfoAmount"); + m_outGainModel.loadSettings( _this, "OutGain" ); } @@ -60,6 +64,7 @@ void DelayControls::saveSettings( QDomDocument& doc, QDomElement& _this ) m_feedbackModel.saveSettings( doc, _this ,"FeebackAmount" ); m_lfoTimeModel.saveSettings( doc, _this, "LfoFrequency" ); m_lfoAmountModel.saveSettings( doc, _this ,"LfoAmount" ); + m_outGainModel.saveSettings( doc, _this, "OutGain" ); } diff --git a/plugins/delay/delaycontrols.h b/plugins/Delay/DelayControls.h similarity index 94% rename from plugins/delay/delaycontrols.h rename to plugins/Delay/DelayControls.h index a02758ebb..1cd987152 100644 --- a/plugins/delay/delaycontrols.h +++ b/plugins/Delay/DelayControls.h @@ -27,7 +27,7 @@ #include "EffectControls.h" #include "Knob.h" -#include "delaycontrolsdialog.h" +#include "DelayControlsDialog.h" @@ -48,13 +48,17 @@ public: return "Delay"; } virtual int controlCount(){ - return 4; + return 5; } virtual EffectControlDialog* createView() { return new DelayControlsDialog( this ); } + float m_outPeakL; + float m_outPeakR; + + private slots: void changeSampleRate(); @@ -64,6 +68,7 @@ private: FloatModel m_feedbackModel; TempoSyncKnobModel m_lfoTimeModel; TempoSyncKnobModel m_lfoAmountModel; + FloatModel m_outGainModel; friend class DelayControlsDialog; friend class DelayEffect; diff --git a/plugins/delay/delaycontrolsdialog.cpp b/plugins/Delay/DelayControlsDialog.cpp similarity index 50% rename from plugins/delay/delaycontrolsdialog.cpp rename to plugins/Delay/DelayControlsDialog.cpp index aae4c0aa4..7da0cf49f 100644 --- a/plugins/delay/delaycontrolsdialog.cpp +++ b/plugins/Delay/DelayControlsDialog.cpp @@ -22,10 +22,13 @@ * */ -#include "delaycontrolsdialog.h" -#include "delaycontrols.h" +#include "DelayControlsDialog.h" +#include "DelayControls.h" #include "embed.h" #include "TempoSyncKnob.h" +#include "../Eq/EqFader.h" +#include +#include @@ -37,37 +40,112 @@ DelayControlsDialog::DelayControlsDialog( DelayControls *controls ) : QPalette pal; pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap( "artwork" ) ); setPalette( pal ); - setFixedSize( 200, 75 ); + setFixedSize( 300, 200 ); TempoSyncKnob* sampleDelayKnob = new TempoSyncKnob( knobBright_26, this ); - sampleDelayKnob->move( 20,10 ); + sampleDelayKnob->move( 13,10 ); sampleDelayKnob->setVolumeKnob( false ); sampleDelayKnob->setModel( &controls->m_delayTimeModel ); sampleDelayKnob->setLabel( tr( "Delay" ) ); sampleDelayKnob->setHintText( tr( "Delay Time" ) + " ", " s" ); Knob * feedbackKnob = new Knob( knobBright_26, this ); - feedbackKnob->move( 63,10 ); + feedbackKnob->move( 13, 55 ); feedbackKnob->setVolumeKnob( true) ; feedbackKnob->setModel( &controls->m_feedbackModel); feedbackKnob->setLabel( tr( "Regen" ) ); feedbackKnob->setHintText( tr ( "Feedback Amount" ) + " " , "" ); TempoSyncKnob * lfoFreqKnob = new TempoSyncKnob( knobBright_26, this ); - lfoFreqKnob->move( 106,10 ); + lfoFreqKnob->move( 13, 100 ); lfoFreqKnob->setVolumeKnob( false ); lfoFreqKnob->setModel( &controls->m_lfoTimeModel ); lfoFreqKnob->setLabel( tr( "Rate" ) ); lfoFreqKnob->setHintText( tr ( "Lfo") + " ", " s" ); TempoSyncKnob * lfoAmtKnob = new TempoSyncKnob( knobBright_26, this ); - lfoAmtKnob->move( 150,10 ); + lfoAmtKnob->move( 13, 145 ); lfoAmtKnob->setVolumeKnob( false ); lfoAmtKnob->setModel( &controls->m_lfoAmountModel ); lfoAmtKnob->setLabel( tr( "Lfo" ) ); lfoAmtKnob->setHintText( tr ( "Lfo Amt" ) + " " , " s" ); + EqFader * outFader = new EqFader( &controls->m_outGainModel,tr( "Out Gain" ), + this, &controls->m_outPeakL, &controls->m_outPeakR ); + outFader->setMaximumHeight( 196 ); + outFader->move( 263, 42 ); + outFader->setDisplayConversion( false ); + outFader->setHintText( tr( "Gain" ), "dBv" ); + XyPad * pad = new XyPad( this, &controls->m_feedbackModel, &controls->m_delayTimeModel ); + pad->resize( 196, 196 ); + pad->move( 50, 2 ); } + + +XyPad::XyPad(QWidget *parent, FloatModel *xModel, FloatModel *yModel) : + QWidget( parent ), + m_xModel( xModel ), + m_yModel( yModel ), + m_acceptInput( false ) +{ + connect( m_xModel, SIGNAL( dataChanged() ) , this, SLOT( update() ) ); + connect( m_yModel, SIGNAL( dataChanged() ) , this, SLOT( update() ) ); +} + + + + +void XyPad::paintEvent(QPaintEvent *event) +{ + QPainter painter( this ); + //Draw Frequecy maker lines + painter.setPen( QPen( QColor( 200, 200, 200, 200 ), 8, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin ) ); + float xRange = m_xModel->maxValue() - m_xModel->minValue(); + float xInc = xRange / width(); + int xPos = ( m_xModel->value() - m_xModel->minValue() ) / xInc; + + float yRange = m_yModel->maxValue() - m_yModel->minValue(); + float yInc = yRange / height(); + int yPos = ( m_yModel->value() - m_yModel->minValue() ) / yInc; + + painter.drawPoint( xPos, yPos ); +} + + + + +void XyPad::mousePressEvent(QMouseEvent *event) +{ + m_acceptInput = true; +} + + + + +void XyPad::mouseReleaseEvent(QMouseEvent *event) +{ + m_acceptInput = false; +} + + + + +void XyPad::mouseMoveEvent(QMouseEvent *event) +{ + if( m_acceptInput && (event->x() >= 0) && ( event->x() < width() ) + && ( event->y() >= 0) && ( event->y() < height() ) ) + { + //set xmodel + float xRange = m_xModel->maxValue() - m_xModel->minValue(); + float xInc = xRange / width(); + m_xModel->setValue( m_xModel->minValue() + ( event->x() * xInc ) ); + + //set ymodel + float yRange = m_yModel->maxValue() - m_yModel->minValue(); + float yInc = yRange / height(); + m_yModel->setValue( m_yModel->minValue() + ( event->y() * yInc ) ); + } +} diff --git a/plugins/delay/delaycontrolsdialog.h b/plugins/Delay/DelayControlsDialog.h similarity index 72% rename from plugins/delay/delaycontrolsdialog.h rename to plugins/Delay/DelayControlsDialog.h index 9afe1d7c7..386c97052 100644 --- a/plugins/delay/delaycontrolsdialog.h +++ b/plugins/Delay/DelayControlsDialog.h @@ -26,6 +26,7 @@ #define DELAYCONTROLSDIALOG_H #include "EffectControlDialog.h" +#include "AutomatableModel.h" class DelayControls; @@ -38,4 +39,23 @@ public: } }; +class XyPad : public QWidget +{ + Q_OBJECT +public: + XyPad( QWidget *parent = 0, FloatModel *xModel = 0, FloatModel *yModel = 0 ); + ~XyPad() {} + +protected: + virtual void paintEvent ( QPaintEvent * event ); + virtual void mousePressEvent(QMouseEvent * event ); + virtual void mouseReleaseEvent(QMouseEvent * event); + virtual void mouseMoveEvent(QMouseEvent * event); + +private: + FloatModel *m_xModel; + FloatModel *m_yModel; + bool m_acceptInput; +}; + #endif // DELAYCONTROLSDIALOG_H diff --git a/plugins/delay/delayeffect.cpp b/plugins/Delay/DelayEffect.cpp similarity index 57% rename from plugins/delay/delayeffect.cpp rename to plugins/Delay/DelayEffect.cpp index 4e5bcd95e..7f41653a2 100644 --- a/plugins/delay/delayeffect.cpp +++ b/plugins/Delay/DelayEffect.cpp @@ -22,9 +22,10 @@ * */ -#include "delayeffect.h" +#include "DelayEffect.h" #include "Engine.h" #include "embed.cpp" +#include "interpolation.h" extern "C" @@ -53,6 +54,7 @@ DelayEffect::DelayEffect( Model* parent, const Plugin::Descriptor::SubPluginFeat m_delay = 0; m_delay = new StereoDelay( 20, Engine::mixer()->processingSampleRate() ); m_lfo = new Lfo( Engine::mixer()->processingSampleRate() ); + m_outGain = 1.0; } @@ -80,25 +82,65 @@ bool DelayEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames ) return( false ); } double outSum = 0.0; + const float sr = Engine::mixer()->processingSampleRate(); const float d = dryLevel(); const float w = wetLevel(); - const float length = m_delayControls.m_delayTimeModel.value() * Engine::mixer()->processingSampleRate(); - const float amplitude = m_delayControls.m_lfoAmountModel.value() * Engine::mixer()->processingSampleRate(); - m_lfo->setFrequency( 1.0 / m_delayControls.m_lfoTimeModel.value() ); - m_delay->setFeedback( m_delayControls.m_feedbackModel.value() ); sample_t dryS[2]; + float lPeak = 0.0; + float rPeak = 0.0; + float length = m_delayControls.m_delayTimeModel.value(); + float amplitude = m_delayControls.m_lfoAmountModel.value() * sr; + float lfoTime = 1.0 / m_delayControls.m_lfoTimeModel.value(); + float feedback = m_delayControls.m_feedbackModel.value(); + ValueBuffer *lengthBuffer = m_delayControls.m_delayTimeModel.valueBuffer(); + ValueBuffer *feedbackBuffer = m_delayControls.m_feedbackModel.valueBuffer(); + ValueBuffer *lfoTimeBuffer = m_delayControls.m_lfoTimeModel.valueBuffer(); + ValueBuffer *lfoAmountBuffer = m_delayControls.m_lfoAmountModel.valueBuffer(); + int lengthInc = lengthBuffer ? 1 : 0; + int amplitudeInc = lfoAmountBuffer ? 1 : 0; + int lfoTimeInc = lfoTimeBuffer ? 1 : 0; + int feedbackInc = feedbackBuffer ? 1 : 0; + float *lengthPtr = lengthBuffer ? &( lengthBuffer->values()[ 0 ] ) : &length; + float *amplitudePtr = lfoAmountBuffer ? &( lfoAmountBuffer->values()[ 0 ] ) : &litude; + float *lfoTimePtr = lfoTimeBuffer ? &( lfoTimeBuffer->values()[ 0 ] ) : &lfoTime; + float *feedbackPtr = feedbackBuffer ? &( feedbackBuffer->values()[ 0 ] ) : &feedback; + + if( m_delayControls.m_outGainModel.isValueChanged() ) + { + m_outGain = dbvToAmp( m_delayControls.m_outGainModel.value() ); + } + int sampleLength; for( fpp_t f = 0; f < frames; ++f ) { dryS[0] = buf[f][0]; dryS[1] = buf[f][1]; - m_delay->setLength( ( float )length + ( amplitude * ( float )m_lfo->tick() ) ); + + m_delay->setFeedback( *feedbackPtr ); + m_lfo->setFrequency( *lfoTimePtr ); + sampleLength = *lengthPtr * Engine::mixer()->processingSampleRate(); + m_currentLength = linearInterpolate( sampleLength, m_currentLength, 0.9999 ); + m_delay->setLength( m_currentLength + ( *amplitudePtr * ( float )m_lfo->tick() ) ); m_delay->tick( buf[f] ); + buf[f][0] *= m_outGain; + buf[f][1] *= m_outGain; + + lPeak = buf[f][0] > lPeak ? buf[f][0] : lPeak; + rPeak = buf[f][1] > rPeak ? buf[f][1] : rPeak; + buf[f][0] = ( d * dryS[0] ) + ( w * buf[f][0] ); buf[f][1] = ( d * dryS[1] ) + ( w * buf[f][1] ); outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1]; + + lengthPtr += lengthInc; + amplitudePtr += amplitudeInc; + lfoTimePtr += lfoTimeInc; + feedbackPtr += feedbackInc; } checkGate( outSum / frames ); + m_delayControls.m_outPeakL = lPeak; + m_delayControls.m_outPeakR = rPeak; + return isRunning(); } diff --git a/plugins/delay/delayeffect.h b/plugins/Delay/DelayEffect.h similarity index 91% rename from plugins/delay/delayeffect.h rename to plugins/Delay/DelayEffect.h index 21aa31b5e..af4f86b07 100644 --- a/plugins/delay/delayeffect.h +++ b/plugins/Delay/DelayEffect.h @@ -26,9 +26,10 @@ #define DELAYEFFECT_H #include "Effect.h" -#include "delaycontrols.h" -#include "lfo.h" -#include "stereodelay.h" +#include "DelayControls.h" +#include "Lfo.h" +#include "StereoDelay.h" +#include "ValueBuffer.h" class DelayEffect : public Effect { @@ -46,6 +47,8 @@ private: DelayControls m_delayControls; StereoDelay* m_delay; Lfo* m_lfo; + float m_outGain; + float m_currentLength; }; #endif // DELAYEFFECT_H diff --git a/plugins/delay/lfo.cpp b/plugins/Delay/Lfo.cpp similarity index 98% rename from plugins/delay/lfo.cpp rename to plugins/Delay/Lfo.cpp index 8936bd186..42809f343 100644 --- a/plugins/delay/lfo.cpp +++ b/plugins/Delay/Lfo.cpp @@ -22,7 +22,7 @@ * */ -#include "lfo.h" +#include "Lfo.h" #include "lmms_math.h" diff --git a/plugins/delay/lfo.h b/plugins/Delay/Lfo.h similarity index 100% rename from plugins/delay/lfo.h rename to plugins/Delay/Lfo.h diff --git a/plugins/delay/stereodelay.cpp b/plugins/Delay/StereoDelay.cpp similarity index 96% rename from plugins/delay/stereodelay.cpp rename to plugins/Delay/StereoDelay.cpp index 9bdf29fdb..21e637740 100644 --- a/plugins/delay/stereodelay.cpp +++ b/plugins/Delay/StereoDelay.cpp @@ -22,7 +22,7 @@ * */ -#include "stereodelay.h" +#include "StereoDelay.h" #include #include "lmms_basics.h" #include "interpolation.h" @@ -74,7 +74,7 @@ void StereoDelay::tick( sampleFrame frame ) m_buffer[m_index][0] += frame[0] * m_feedback; m_buffer[m_index][1] += frame[1] * m_feedback; - m_index = ( m_index + 1) % m_maxLength; + m_index = ( m_index + 1) % (int) m_maxLength; } diff --git a/plugins/delay/stereodelay.h b/plugins/Delay/StereoDelay.h similarity index 100% rename from plugins/delay/stereodelay.h rename to plugins/Delay/StereoDelay.h diff --git a/plugins/Delay/artwork.png b/plugins/Delay/artwork.png new file mode 100644 index 000000000..2ac7a2f74 Binary files /dev/null and b/plugins/Delay/artwork.png differ diff --git a/plugins/delay/logo.png b/plugins/Delay/logo.png similarity index 100% rename from plugins/delay/logo.png rename to plugins/Delay/logo.png diff --git a/plugins/DualFilter/DualFilter.cpp b/plugins/DualFilter/DualFilter.cpp index 035740dbf..c78d68a29 100644 --- a/plugins/DualFilter/DualFilter.cpp +++ b/plugins/DualFilter/DualFilter.cpp @@ -95,33 +95,52 @@ bool DualFilterEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames m_filter2changed = true; } + float cut1 = m_dfControls.m_cut1Model.value(); + float res1 = m_dfControls.m_res1Model.value(); + float gain1 = m_dfControls.m_gain1Model.value(); + float cut2 = m_dfControls.m_cut2Model.value(); + float res2 = m_dfControls.m_res2Model.value(); + float gain2 = m_dfControls.m_gain2Model.value(); + float mix = m_dfControls.m_mixModel.value(); + + ValueBuffer *cut1Buffer = m_dfControls.m_cut1Model.valueBuffer(); + ValueBuffer *res1Buffer = m_dfControls.m_res1Model.valueBuffer(); + ValueBuffer *gain1Buffer = m_dfControls.m_gain1Model.valueBuffer(); + ValueBuffer *cut2Buffer = m_dfControls.m_cut2Model.valueBuffer(); + ValueBuffer *res2Buffer = m_dfControls.m_res2Model.valueBuffer(); + ValueBuffer *gain2Buffer = m_dfControls.m_gain2Model.valueBuffer(); + ValueBuffer *mixBuffer = m_dfControls.m_mixModel.valueBuffer(); + + int cut1Inc = cut1Buffer ? 1 : 0; + int res1Inc = res1Buffer ? 1 : 0; + int gain1Inc = gain1Buffer ? 1 : 0; + int cut2Inc = cut2Buffer ? 1 : 0; + int res2Inc = res2Buffer ? 1 : 0; + int gain2Inc = gain2Buffer ? 1 : 0; + int mixInc = mixBuffer ? 1 : 0; + + float *cut1Ptr = cut1Buffer ? &( cut1Buffer->values()[ 0 ] ) : &cut1; + float *res1Ptr = res1Buffer ? &( res1Buffer->values()[ 0 ] ) : &res1; + float *gain1Ptr = gain1Buffer ? &( gain1Buffer->values()[ 0 ] ) : &gain1; + float *cut2Ptr = cut2Buffer ? &( cut2Buffer->values()[ 0 ] ) : &cut2; + float *res2Ptr = res2Buffer ? &( res2Buffer->values()[ 0 ] ) : &res2; + float *gain2Ptr = gain2Buffer ? &( gain2Buffer->values()[ 0 ] ) : &gain2; + float *mixPtr = mixBuffer ? &( mixBuffer->values()[ 0 ] ) : &mix; + const bool enabled1 = m_dfControls.m_enabled1Model.value(); const bool enabled2 = m_dfControls.m_enabled2Model.value(); - // recalculate only when necessary: either cut/res is changed, or the changed-flag is set (filter type or samplerate changed) - if( ( enabled1 && ( m_dfControls.m_cut1Model.isValueChanged() || - m_dfControls.m_res1Model.isValueChanged() ) ) || m_filter1changed ) - { - m_filter1->calcFilterCoeffs( m_dfControls.m_cut1Model.value(), m_dfControls.m_res1Model.value() ); - m_filter1changed = false; - } - if( ( enabled2 && ( m_dfControls.m_cut2Model.isValueChanged() || - m_dfControls.m_res2Model.isValueChanged() ) ) || m_filter2changed ) - { - m_filter2->calcFilterCoeffs( m_dfControls.m_cut2Model.value(), m_dfControls.m_res2Model.value() ); - m_filter2changed = false; - } - // get mix amounts for wet signals of both filters - const float mix2 = ( ( m_dfControls.m_mixModel.value() + 1.0f ) * 0.5f ); - const float mix1 = 1.0f - mix2; - const float gain1 = m_dfControls.m_gain1Model.value() * 0.01f; - const float gain2 = m_dfControls.m_gain2Model.value() * 0.01f; // buffer processing loop for( fpp_t f = 0; f < frames; ++f ) { + // get mix amounts for wet signals of both filters + const float mix2 = ( ( *mixPtr + 1.0f ) * 0.5f ); + const float mix1 = 1.0f - mix2; + const float gain1 = *gain1Ptr * 0.01f; + const float gain2 = *gain2Ptr * 0.01f; sample_t s[2] = { 0.0f, 0.0f }; // mix sample_t s1[2] = { buf[f][0], buf[f][1] }; // filter 1 sample_t s2[2] = { buf[f][0], buf[f][1] }; // filter 2 @@ -129,6 +148,16 @@ bool DualFilterEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames // update filter 1 if( enabled1 ) { + //update filter 1 params here + // recalculate only when necessary: either cut/res is changed, or the changed-flag is set (filter type or samplerate changed) + if( ( ( *cut1Ptr != m_currentCut1 || + *res1Ptr != m_currentRes1 ) ) || m_filter1changed ) + { + m_filter1->calcFilterCoeffs( *cut1Ptr, *res2Ptr ); + m_filter1changed = false; + m_currentCut1 = *cut1Ptr; + m_currentRes1 = *res1Ptr; + } s1[0] = m_filter1->update( s1[0], 0 ); s1[1] = m_filter1->update( s1[1], 1 ); @@ -144,6 +173,15 @@ bool DualFilterEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames // update filter 2 if( enabled2 ) { + //update filter 2 params here + if( ( ( *cut2Ptr != m_currentCut2 || + *res2Ptr != m_currentRes2 ) ) || m_filter2changed ) + { + m_filter2->calcFilterCoeffs( *cut2Ptr, *res2Ptr ); + m_filter2changed = false; + m_currentCut2 = *cut2Ptr; + m_currentRes2 = *res2Ptr; + } s2[0] = m_filter2->update( s2[0], 0 ); s2[1] = m_filter2->update( s2[1], 1 ); @@ -160,6 +198,15 @@ bool DualFilterEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames // do another mix with dry signal buf[f][0] = d * buf[f][0] + w * s[0]; buf[f][1] = d * buf[f][1] + w * s[1]; + + //increment pointers + cut1Ptr += cut1Inc; + res1Ptr += res1Inc; + gain1Ptr += gain1Inc; + cut2Ptr += cut2Inc; + res2Ptr += res2Inc; + gain2Ptr += gain2Inc; + mixPtr += mixInc; } checkGate( outSum / frames ); diff --git a/plugins/DualFilter/DualFilter.h b/plugins/DualFilter/DualFilter.h index 851531333..561f04dd6 100644 --- a/plugins/DualFilter/DualFilter.h +++ b/plugins/DualFilter/DualFilter.h @@ -53,6 +53,11 @@ private: bool m_filter1changed; bool m_filter2changed; + float m_currentCut1; + float m_currentRes1; + float m_currentCut2; + float m_currentRes2; + friend class DualFilterControls; } ; diff --git a/plugins/Eq/EqEffect.cpp b/plugins/Eq/EqEffect.cpp index 885eebe2a..01830ce10 100644 --- a/plugins/Eq/EqEffect.cpp +++ b/plugins/Eq/EqEffect.cpp @@ -71,6 +71,101 @@ EqEffect::~EqEffect() bool EqEffect::processAudioBuffer(sampleFrame *buf, const fpp_t frames) { + // setup sample exact controls + float hpRes = m_eqControls.m_hpResModel.value(); + float lowShelfRes = m_eqControls.m_lowShelfResModel.value(); + float para1Bw = m_eqControls.m_para1BwModel.value(); + float para2Bw = m_eqControls.m_para2BwModel.value(); + float para3Bw = m_eqControls.m_para3BwModel.value(); + float para4Bw = m_eqControls.m_para4BwModel.value(); + float highShelfRes = m_eqControls.m_highShelfResModel.value(); + float lpRes = m_eqControls.m_lpResModel.value(); + + float hpFreq = m_eqControls.m_hpFeqModel.value(); + float lowShelfFreq = m_eqControls.m_lowShelfFreqModel.value(); + float para1Freq = m_eqControls.m_para1FreqModel.value(); + float para2Freq = m_eqControls.m_para2FreqModel.value(); + float para3Freq = m_eqControls.m_para3FreqModel.value(); + float para4Freq = m_eqControls.m_para4FreqModel.value(); + float highShelfFreq = m_eqControls.m_highShelfFreqModel.value(); + float lpFreq = m_eqControls.m_lpFreqModel.value(); + + ValueBuffer *hpResBuffer = m_eqControls.m_hpResModel.valueBuffer(); + ValueBuffer *lowShelfResBuffer = m_eqControls.m_lowShelfResModel.valueBuffer(); + ValueBuffer *para1BwBuffer = m_eqControls.m_para1BwModel.valueBuffer(); + ValueBuffer *para2BwBuffer = m_eqControls.m_para2BwModel.valueBuffer(); + ValueBuffer *para3BwBuffer = m_eqControls.m_para3BwModel.valueBuffer(); + ValueBuffer *para4BwBuffer = m_eqControls.m_para4BwModel.valueBuffer(); + ValueBuffer *highShelfResBuffer = m_eqControls.m_highShelfResModel.valueBuffer(); + ValueBuffer *lpResBuffer = m_eqControls.m_lpResModel.valueBuffer(); + + ValueBuffer *hpFreqBuffer = m_eqControls.m_hpFeqModel.valueBuffer(); + ValueBuffer *lowShelfFreqBuffer = m_eqControls.m_lowShelfFreqModel.valueBuffer(); + ValueBuffer *para1FreqBuffer = m_eqControls.m_para1FreqModel.valueBuffer(); + ValueBuffer *para2FreqBuffer = m_eqControls.m_para2FreqModel.valueBuffer(); + ValueBuffer *para3FreqBuffer = m_eqControls.m_para3FreqModel.valueBuffer(); + ValueBuffer *para4FreqBuffer = m_eqControls.m_para4FreqModel.valueBuffer(); + ValueBuffer *highShelfFreqBuffer = m_eqControls.m_highShelfFreqModel.valueBuffer(); + ValueBuffer *lpFreqBuffer = m_eqControls.m_lpFreqModel.valueBuffer(); + + int hpResInc = hpResBuffer ? 1 : 0; + int lowShelfResInc = lowShelfResBuffer ? 1 : 0; + int para1BwInc = para1BwBuffer ? 1 : 0; + int para2BwInc = para2BwBuffer ? 1 : 0; + int para3BwInc = para3BwBuffer ? 1 : 0; + int para4BwInc = para4BwBuffer ? 1 : 0; + int highShelfResInc = highShelfResBuffer ? 1 : 0; + int lpResInc = lpResBuffer ? 1 : 0; + + int hpFreqInc = hpFreqBuffer ? 1 : 0; + int lowShelfFreqInc = lowShelfFreqBuffer ? 1 : 0; + int para1FreqInc = para1FreqBuffer ? 1 : 0; + int para2FreqInc = para2FreqBuffer ? 1 : 0; + int para3FreqInc = para3FreqBuffer ? 1 : 0; + int para4FreqInc = para4FreqBuffer ? 1 : 0; + int highShelfFreqInc = highShelfFreqBuffer ? 1 : 0; + int lpFreqInc = lpFreqBuffer ? 1 : 0; + + float *hpResPtr = hpResBuffer ? &( hpResBuffer->values()[ 0 ] ) : &hpRes; + float *lowShelfResPtr = lowShelfResBuffer ? &( lowShelfResBuffer->values()[ 0 ] ) : &lowShelfRes; + float *para1BwPtr = para1BwBuffer ? &( para1BwBuffer->values()[ 0 ] ) : ¶1Bw; + float *para2BwPtr = para2BwBuffer ? &( para2BwBuffer->values()[ 0 ] ) : ¶2Bw; + float *para3BwPtr = para3BwBuffer ? &( para3BwBuffer->values()[ 0 ] ) : ¶3Bw; + float *para4BwPtr = para4BwBuffer ? &( para4BwBuffer->values()[ 0 ] ) : ¶4Bw; + float *highShelfResPtr = highShelfResBuffer ? &( highShelfResBuffer->values()[ 0 ] ) : &highShelfRes; + float *lpResPtr = lpResBuffer ? &( lpResBuffer->values()[ 0 ] ) : &lpRes; + + float *hpFreqPtr = hpFreqBuffer ? &( hpFreqBuffer->values()[ 0 ] ) : &hpFreq; + float *lowShelfFreqPtr = lowShelfFreqBuffer ? &( lowShelfFreqBuffer->values()[ 0 ] ) : &lowShelfFreq; + float *para1FreqPtr = para1FreqBuffer ? &(para1FreqBuffer->values()[ 0 ] ) : ¶1Freq; + float *para2FreqPtr = para2FreqBuffer ? &(para2FreqBuffer->values()[ 0 ] ) : ¶2Freq; + float *para3FreqPtr = para3FreqBuffer ? &(para3FreqBuffer->values()[ 0 ] ) : ¶3Freq; + float *para4FreqPtr = para4FreqBuffer ? &(para4FreqBuffer->values()[ 0 ] ) : ¶4Freq; + float *hightShelfFreqPtr = highShelfFreqBuffer ? &(highShelfFreqBuffer->values()[ 0 ] ) : &highShelfFreq; + float *lpFreqPtr = lpFreqBuffer ? &(lpFreqBuffer ->values()[ 0 ] ) : &lpFreq; + + bool hpActive = m_eqControls.m_hpActiveModel.value(); + bool hp24Active = m_eqControls.m_hp24Model.value(); + bool hp48Active = m_eqControls.m_hp48Model.value(); + bool lowShelfActive = m_eqControls.m_lowShelfActiveModel.value(); + bool para1Active = m_eqControls.m_para1ActiveModel.value(); + bool para2Active = m_eqControls.m_para2ActiveModel.value(); + bool para3Active = m_eqControls.m_para3ActiveModel.value(); + bool para4Active = m_eqControls.m_para4ActiveModel.value(); + bool highShelfActive = m_eqControls.m_highShelfActiveModel.value(); + bool lpActive = m_eqControls.m_lpActiveModel.value(); + bool lp24Active = m_eqControls.m_lp24Model.value(); + bool lp48Active = m_eqControls.m_lp48Model.value(); + + float lowShelfGain = m_eqControls.m_lowShelfGainModel.value(); + float para1Gain = m_eqControls.m_para1GainModel.value(); + float para2Gain = m_eqControls.m_para2GainModel.value(); + float para3Gain = m_eqControls.m_para3GainModel.value(); + float para4Gain = m_eqControls.m_para4GainModel.value(); + float highShelfGain = m_eqControls.m_highShelfGainModel.value(); + + + if( !isEnabled() || !isRunning () ) { return( false ); @@ -105,83 +200,126 @@ bool EqEffect::processAudioBuffer(sampleFrame *buf, const fpp_t frames) m_eqControls.m_inPeakL = m_eqControls.m_inPeakL < m_inPeak[0] ? m_inPeak[0] : m_eqControls.m_inPeakL; m_eqControls.m_inPeakR = m_eqControls.m_inPeakR < m_inPeak[1] ? m_inPeak[1] : m_eqControls.m_inPeakR; - if(m_eqControls.m_hpActiveModel.value() ){ + for( fpp_t f = 0; f < frames; f++) + { + if( hpActive ){ - m_hp12.setParameters( sampleRate, m_eqControls.m_hpFeqModel.value(), m_eqControls.m_hpResModel.value(), 1 ); - m_hp12.processBuffer( buf, frames ); + m_hp12.setParameters( sampleRate, *hpFreqPtr, *hpResPtr, 1 ); + buf[f][0] = m_hp12.update( buf[f][0], 0 ); + buf[f][1] = m_hp12.update( buf[f][1], 1 ); - if( m_eqControls.m_hp24Model.value() || m_eqControls.m_hp48Model.value() ) - { - m_hp24.setParameters( sampleRate, m_eqControls.m_hpFeqModel.value(), m_eqControls.m_hpResModel.value(), 1 ); - m_hp24.processBuffer( buf, frames ); + if( hp24Active || hp48Active ) + { + m_hp24.setParameters( sampleRate, *hpFreqPtr, *hpResPtr, 1 ); + buf[f][0] = m_hp24.update( buf[f][0], 0 ); + buf[f][1] = m_hp24.update( buf[f][1], 1 ); + } + + if( hp48Active ) + { + m_hp480.setParameters( sampleRate, *hpFreqPtr, *hpResPtr, 1 ); + buf[f][0] = m_hp480.update( buf[f][0], 0 ); + buf[f][1] = m_hp480.update( buf[f][1], 1 ); + + m_hp481.setParameters( sampleRate, *hpFreqPtr, *hpResPtr, 1 ); + buf[f][0] = m_hp481.update( buf[f][0], 0 ); + buf[f][1] = m_hp481.update( buf[f][1], 1 ); + } } - if( m_eqControls.m_hp48Model.value() ) + if( lowShelfActive ) { - m_hp480.setParameters( sampleRate, m_eqControls.m_hpFeqModel.value(), m_eqControls.m_hpResModel.value(), 1 ); - m_hp480.processBuffer( buf, frames ); - - m_hp481.setParameters( sampleRate, m_eqControls.m_hpFeqModel.value(), m_eqControls.m_hpResModel.value(), 1 ); - m_hp481.processBuffer( buf, frames ); - } - } - - if( m_eqControls.m_lowShelfActiveModel.value() ) - { - m_lowShelf.setParameters( sampleRate, m_eqControls.m_lowShelfFreqModel.value(), m_eqControls.m_lowShelfResModel .value(), m_eqControls.m_lowShelfGainModel.value() ); - m_lowShelf.processBuffer( buf, frames ); - } - - if( m_eqControls.m_para1ActiveModel.value() ) - { - m_para1.setParameters( sampleRate, m_eqControls.m_para1FreqModel.value(), m_eqControls.m_para1BwModel.value(), m_eqControls.m_para1GainModel.value() ); - m_para1.processBuffer( buf, frames ); - } - - if( m_eqControls.m_para2ActiveModel.value() ) - { - m_para2.setParameters( sampleRate, m_eqControls.m_para2FreqModel.value(), m_eqControls.m_para2BwModel.value(), m_eqControls.m_para2GainModel.value() ); - m_para2.processBuffer( buf, frames ); - } - - if( m_eqControls.m_para3ActiveModel.value() ) - { - m_para3.setParameters( sampleRate, m_eqControls.m_para3FreqModel.value(), m_eqControls.m_para3BwModel.value(), m_eqControls.m_para3GainModel.value() ); - m_para3.processBuffer( buf, frames ); - } - - if( m_eqControls.m_para4ActiveModel.value() ) - { - m_para4.setParameters( sampleRate, m_eqControls.m_para4FreqModel.value(), m_eqControls.m_para4BwModel.value(), m_eqControls.m_para4GainModel.value() ); - m_para4.processBuffer( buf, frames ); - } - - if( m_eqControls.m_highShelfActiveModel.value() ) - { - m_highShelf.setParameters( sampleRate, m_eqControls.m_highShelfFreqModel.value(), m_eqControls.m_highShelfResModel.value(), m_eqControls.m_highShelfGainModel.value()); - m_highShelf.processBuffer( buf, frames ); - } - - if(m_eqControls.m_lpActiveModel.value() ){ - m_lp12.setParameters( sampleRate, m_eqControls.m_lpFreqModel.value(), m_eqControls.m_lpResModel.value(), 1 ); - m_lp12.processBuffer( buf, frames ); - - if( m_eqControls.m_lp24Model.value() || m_eqControls.m_lp48Model.value() ) - { - m_lp24.setParameters( sampleRate, m_eqControls.m_lpFreqModel.value(), m_eqControls.m_lpResModel.value(), 1 ); - m_lp24.processBuffer( buf, frames ); + m_lowShelf.setParameters( sampleRate, *lowShelfFreqPtr, *lowShelfResPtr, lowShelfGain ); + buf[f][0] = m_lowShelf.update( buf[f][0], 0 ); + buf[f][1] = m_lowShelf.update( buf[f][1], 1 ); } - if( m_eqControls.m_lp48Model.value() ) + if( para1Active ) { - m_lp480.setParameters( sampleRate, m_eqControls.m_lpFreqModel.value(), m_eqControls.m_lpResModel.value(), 1 ); - m_lp480.processBuffer( buf, frames ); - - m_lp481.setParameters( sampleRate, m_eqControls.m_lpFreqModel.value(), m_eqControls.m_lpResModel.value(), 1 ); - m_lp481.processBuffer( buf, frames ); + m_para1.setParameters( sampleRate, *para1FreqPtr, *para1BwPtr, para1Gain ); + buf[f][0] = m_para1.update( buf[f][0], 0 ); + buf[f][1] = m_para1.update( buf[f][1], 1 ); } + + if( para2Active ) + { + m_para2.setParameters( sampleRate, *para2FreqPtr, *para2BwPtr, para2Gain ); + buf[f][0] = m_para2.update( buf[f][0], 0 ); + buf[f][1] = m_para2.update( buf[f][1], 1 ); + } + + if( para3Active ) + { + m_para3.setParameters( sampleRate, *para3FreqPtr, *para3BwPtr, para3Gain ); + buf[f][0] = m_para3.update( buf[f][0], 0 ); + buf[f][1] = m_para3.update( buf[f][1], 1 ); + } + + if( para4Active ) + { + m_para4.setParameters( sampleRate, *para4FreqPtr, *para4BwPtr, para4Gain ); + buf[f][0] = m_para4.update( buf[f][0], 0 ); + buf[f][1] = m_para4.update( buf[f][1], 1 ); + } + + if( highShelfActive ) + { + m_highShelf.setParameters( sampleRate, *hightShelfFreqPtr, *highShelfResPtr, highShelfGain ); + buf[f][0] = m_highShelf.update( buf[f][0], 0 ); + buf[f][1] = m_highShelf.update( buf[f][1], 1 ); + } + + if( lpActive ){ + m_lp12.setParameters( sampleRate, *lpFreqPtr, *lpResPtr, 1 ); + buf[f][0] = m_lp12.update( buf[f][0], 0 ); + buf[f][1] = m_lp12.update( buf[f][1], 1 ); + + if( lp24Active || lp48Active ) + { + m_lp24.setParameters( sampleRate, *lpFreqPtr, *lpResPtr, 1 ); + buf[f][0] = m_lp24.update( buf[f][0], 0 ); + buf[f][1] = m_lp24.update( buf[f][1], 1 ); + } + + if( lp48Active ) + { + m_lp480.setParameters( sampleRate, *lpFreqPtr, *lpResPtr, 1 ); + buf[f][0] = m_lp480.update( buf[f][0], 0 ); + buf[f][1] = m_lp480.update( buf[f][1], 1 ); + + m_lp481.setParameters( sampleRate, *lpFreqPtr, *lpResPtr, 1 ); + buf[f][0] = m_lp481.update( buf[f][0], 0 ); + buf[f][1] = m_lp481.update( buf[f][1], 1 ); + } + } + + //increment pointers if needed + hpResPtr += hpResInc; + lowShelfResPtr += lowShelfResInc; + para1BwPtr += para1BwInc; + para2BwPtr += para2BwInc; + para3BwPtr += para3BwInc; + para4BwPtr += para4BwInc; + highShelfResPtr += highShelfResInc; + lpResPtr += lpResInc; + + hpFreqPtr += hpFreqInc; + lowShelfFreqPtr += lowShelfFreqInc; + para1FreqPtr += para1FreqInc; + para2FreqPtr += para2FreqInc; + para3FreqPtr += para3FreqInc; + para4FreqPtr += para4FreqInc; + hightShelfFreqPtr += highShelfFreqInc; + lpFreqPtr += lpFreqInc; } + + + + + + + sampleFrame outPeak = { 0, 0 }; gain( buf, frames, outGain, &outPeak ); m_eqControls.m_outPeakL = m_eqControls.m_outPeakL < outPeak[0] ? outPeak[0] : m_eqControls.m_outPeakL; diff --git a/plugins/Eq/EqFilter.h b/plugins/Eq/EqFilter.h index 7e75a2e6c..37cef312d 100644 --- a/plugins/Eq/EqFilter.h +++ b/plugins/Eq/EqFilter.h @@ -122,19 +122,6 @@ public: - /// - /// \brief processBuffer - /// \param buf Audio Buffer - /// \param frames Count of sampleFrames in Audio Buffer - /// - virtual void processBuffer( sampleFrame* buf, const fpp_t frames ) - { - for ( fpp_t f = 0 ; f < frames ; ++f) - { - buf[f][0] = update( buf[f][0] , 0); - buf[f][1] = update( buf[f][1] , 1); - } - } protected: /// diff --git a/plugins/LadspaEffect/swh/CMakeLists.txt b/plugins/LadspaEffect/swh/CMakeLists.txt index 7d57d9cdb..623da38bc 100644 --- a/plugins/LadspaEffect/swh/CMakeLists.txt +++ b/plugins/LadspaEffect/swh/CMakeLists.txt @@ -24,9 +24,9 @@ FOREACH(_item ${PLUGIN_SOURCES}) ELSE(LMMS_BUILD_APPLE) SET_TARGET_PROPERTIES("${_plugin}" PROPERTIES LINK_FLAGS "${LINK_FLAGS} -shared -Wl,-no-undefined -Wl,-Bsymbolic -lm") ENDIF(LMMS_BUILD_APPLE) - IF(LMMS_BUILD_LINUX) + IF(LMMS_BUILD_LINUX OR LMMS_BUILD_HAIKU) SET_TARGET_PROPERTIES("${_plugin}" PROPERTIES LINK_FLAGS "${LINK_FLAGS} -nostartfiles") - ENDIF(LMMS_BUILD_LINUX) + ENDIF(LMMS_BUILD_LINUX OR LMMS_BUILD_HAIKU) ENDFOREACH(_item ${PLUGIN_SOURCES}) diff --git a/plugins/LadspaEffect/tap/CMakeLists.txt b/plugins/LadspaEffect/tap/CMakeLists.txt index e8bc12017..d9fdc3861 100644 --- a/plugins/LadspaEffect/tap/CMakeLists.txt +++ b/plugins/LadspaEffect/tap/CMakeLists.txt @@ -14,8 +14,8 @@ FOREACH(_item ${PLUGIN_SOURCES}) ELSE(LMMS_BUILD_APPLE) SET_TARGET_PROPERTIES("${_plugin}" PROPERTIES LINK_FLAGS "${LINK_FLAGS} -shared -Wl,-no-undefined -Wl,-Bsymbolic -lm") ENDIF(LMMS_BUILD_APPLE) - IF(LMMS_BUILD_LINUX) + IF(LMMS_BUILD_LINUX OR LMMS_BUILD_HAIKU) SET_TARGET_PROPERTIES("${_plugin}" PROPERTIES LINK_FLAGS "${LINK_FLAGS} -nostartfiles") - ENDIF(LMMS_BUILD_LINUX) + ENDIF(LMMS_BUILD_LINUX OR LMMS_BUILD_HAIKU) ENDFOREACH(_item ${PLUGIN_SOURCES}) diff --git a/plugins/MidiExport/CMakeLists.txt b/plugins/MidiExport/CMakeLists.txt new file mode 100644 index 000000000..1d19f081e --- /dev/null +++ b/plugins/MidiExport/CMakeLists.txt @@ -0,0 +1,4 @@ +INCLUDE(BuildPlugin) + +BUILD_PLUGIN(midiexport MidiExport.cpp MidiExport.h MidiFile.hpp + MOCFILES MidiExport.h) diff --git a/plugins/MidiExport/MidiExport.cpp b/plugins/MidiExport/MidiExport.cpp new file mode 100644 index 000000000..03ef3a496 --- /dev/null +++ b/plugins/MidiExport/MidiExport.cpp @@ -0,0 +1,183 @@ +/* + * MidiExport.cpp - support for importing MIDI files + * + * Author: Mohamed Abdel Maksoud + * + * This file is part of LMMS - http://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 +#include + +#include "MidiExport.h" +#include "Engine.h" +#include "TrackContainer.h" +#include "InstrumentTrack.h" + + +extern "C" +{ + +Plugin::Descriptor PLUGIN_EXPORT midiexport_plugin_descriptor = +{ + STRINGIFY( PLUGIN_NAME ), + "MIDI Export", + QT_TRANSLATE_NOOP( "pluginBrowser", + "Filter for exporting MIDI-files from LMMS" ), + "Mohamed Abdel Maksoud ", + 0x0100, + Plugin::ExportFilter, + NULL, + NULL, + NULL +} ; + +} + + +MidiExport::MidiExport() : ExportFilter( &midiexport_plugin_descriptor) +{ +} + + + + +MidiExport::~MidiExport() +{ +} + + + +bool MidiExport::tryExport( const TrackContainer::TrackList &tracks, int tempo, const QString &filename ) +{ + QFile f(filename); + f.open(QIODevice::WriteOnly); + QDataStream midiout(&f); + + InstrumentTrack* instTrack; + QDomElement element; + + + int nTracks = 0; + const int BUFFER_SIZE = 50*1024; + uint8_t buffer[BUFFER_SIZE]; + uint32_t size; + + foreach( Track* track, tracks ) if( track->type() == Track::InstrumentTrack ) nTracks++; + + // midi header + MidiFile::MIDIHeader header(nTracks); + size = header.writeToBuffer(buffer); + midiout.writeRawData((char *)buffer, size); + + // midi tracks + foreach( Track* track, tracks ) + { + DataFile dataFile( DataFile::SongProject ); + MidiFile::MIDITrack mtrack; + + if( track->type() != Track::InstrumentTrack ) continue; + + //qDebug() << "exporting " << track->name(); + + + mtrack.addName(track->name().toStdString(), 0); + //mtrack.addProgramChange(0, 0); + mtrack.addTempo(tempo, 0); + + instTrack = dynamic_cast( track ); + element = instTrack->saveState( dataFile, dataFile.content() ); + + // instrumentTrack + // - instrumentTrack + // - pattern + int base_pitch = 0; + double base_volume = 1.0; + int base_time = 0; + + + for(QDomNode n = element.firstChild(); !n.isNull(); n = n.nextSibling()) + { + //QDomText txt = n.toText(); + //qDebug() << ">> child node " << n.nodeName(); + + if (n.nodeName() == "instrumenttrack") + { + // TODO interpret pan="0" fxch="0" usemasterpitch="1" pitchrange="1" pitch="0" basenote="57" + QDomElement it = n.toElement(); + base_pitch = it.attribute("pitch", "0").toInt(); + base_volume = it.attribute("volume", "100").toDouble()/100.0; + } + + if (n.nodeName() == "pattern") + { + base_time = n.toElement().attribute("pos", "0").toInt(); + // TODO interpret steps="12" muted="0" type="1" name="Piano1" len="2592" + for(QDomNode nn = n.firstChild(); !nn.isNull(); nn = nn.nextSibling()) + { + QDomElement note = nn.toElement(); + if (note.attribute("len", "0") == "0" || note.attribute("vol", "0") == "0") continue; + #if 0 + qDebug() << ">>>> key " << note.attribute( "key", "0" ) + << " " << note.attribute("len", "0") << " @" + << note.attribute("pos", "0"); + #endif + mtrack.addNote( + note.attribute("key", "0").toInt()+base_pitch + , 100 * base_volume * (note.attribute("vol", "100").toDouble()/100) + , (base_time+note.attribute("pos", "0").toDouble())/48 + , (note.attribute("len", "0")).toDouble()/48); + } + } + + } + size = mtrack.writeToBuffer(buffer); + midiout.writeRawData((char *)buffer, size); + } // for each track + + return true; + +} + + + + +void MidiExport::error() +{ + //qDebug() << "MidiExport error: " << m_error ; +} + + + +extern "C" +{ + +// necessary for getting instance out of shared lib +Plugin * PLUGIN_EXPORT lmms_plugin_main( Model *, void * _data ) +{ + return new MidiExport(); +} + + +} + diff --git a/plugins/MidiExport/MidiExport.h b/plugins/MidiExport/MidiExport.h new file mode 100644 index 000000000..d829a8b8f --- /dev/null +++ b/plugins/MidiExport/MidiExport.h @@ -0,0 +1,58 @@ +/* + * MidiExport.h - support for Exporting MIDI-files + * + * Author: Mohamed Abdel Maksoud + * + * This file is part of LMMS - http://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 _MIDI_EXPORT_H +#define _MIDI_EXPORT_H + +#include + +#include "ExportFilter.h" +#include "MidiFile.hpp" + + + +class MidiExport: public ExportFilter +{ +// Q_OBJECT +public: + MidiExport( ); + ~MidiExport(); + + virtual PluginView * instantiateView( QWidget * ) + { + return( NULL ); + } + + virtual bool tryExport( const TrackContainer::TrackList &tracks, int tempo, const QString &filename ); + +private: + + + void error( void ); + + +} ; + + +#endif diff --git a/plugins/MidiExport/MidiFile.hpp b/plugins/MidiExport/MidiFile.hpp new file mode 100644 index 000000000..0e2bfbe5b --- /dev/null +++ b/plugins/MidiExport/MidiFile.hpp @@ -0,0 +1,308 @@ +#ifndef MIDIFILE_HPP +#define MIDIFILE_HPP + +/** + * Name: MidiFile.hpp + * Purpose: C++ re-write of the python module MidiFile.py + * Author: Mohamed Abdel Maksoud + *----------------------------------------------------------------------------- + * Name: MidiFile.py + * Purpose: MIDI file manipulation utilities + * + * Author: Mark Conway Wirt + * + * Created: 2008/04/17 + * Copyright: (c) 2009 Mark Conway Wirt + * License: Please see License.txt for the terms under which this + * software is distributed. + *----------------------------------------------------------------------------- + */ + +#include +#include +#include +#include +#include +#include +#include + +using std::string; +using std::vector; +using std::set; + +namespace MidiFile +{ + +const int TICKSPERBEAT = 128; + + +int writeVarLength(uint32_t val, uint8_t *buffer) +{ + /* + Accept an input, and write a MIDI-compatible variable length stream + + The MIDI format is a little strange, and makes use of so-called variable + length quantities. These quantities are a stream of bytes. If the most + significant bit is 1, then more bytes follow. If it is zero, then the + byte in question is the last in the stream + */ + int size = 0; + uint8_t result, little_endian[4]; + result = val & 0x7F; + little_endian[size++] = result; + val = val >> 7; + while (val > 0) + { + result = val & 0x7F; + result = result | 0x80; + little_endian[size++] = result; + val = val >> 7; + } + for (int i=0; i> 24; + buf[1] = val >> 16 & 0xff; + buf[2] = val >> 8 & 0xff; + buf[3] = val & 0xff; + return 4; +} + +int writeBigEndian2(uint16_t val, uint8_t *buf) +{ + buf[0] = val >> 8 & 0xff; + buf[1] = val & 0xff; + return 2; +} + + +class MIDIHeader +{ + // Class to encapsulate the MIDI header structure. + uint16_t numTracks; + uint16_t ticksPerBeat; + + public: + + MIDIHeader(uint16_t nTracks, uint16_t ticksPB=TICKSPERBEAT): numTracks(nTracks), ticksPerBeat(ticksPB) {} + + inline int writeToBuffer(uint8_t *buffer, int start=0) const + { + // chunk ID + buffer[start++] = 'M'; buffer[start++] = 'T'; buffer[start++] = 'h'; buffer[start++] = 'd'; + // chunk size (6 bytes always) + buffer[start++] = 0; buffer[start++] = 0; buffer[start++] = 0; buffer[start++] = 0x06; + // format: 1 (multitrack) + buffer[start++] = 0; buffer[start++] = 0x01; + + start += writeBigEndian2(numTracks, buffer+start); + + start += writeBigEndian2(ticksPerBeat, buffer+start); + + return start; + } + +}; + + +struct Event +{ + uint32_t time; + uint32_t tempo; + string trackName; + enum {NOTE_ON, NOTE_OFF, TEMPO, PROG_CHANGE, TRACK_NAME} type; + // TODO make a union to save up space + uint8_t pitch; + uint8_t programNumber; + uint8_t duration; + uint8_t volume; + uint8_t channel; + + Event() {time=tempo=pitch=programNumber=duration=volume=channel=0; trackName="";} + + inline int writeToBuffer(uint8_t *buffer) const + { + uint8_t code, fourbytes[4]; + int size=0; + switch (type) + { + case NOTE_ON: + code = 0x9 << 4 | channel; + size += writeVarLength(time, buffer+size); + buffer[size++] = code; + buffer[size++] = pitch; + buffer[size++] = volume; + break; + case NOTE_OFF: + code = 0x8 << 4 | channel; + size += writeVarLength(time, buffer+size); + buffer[size++] = code; + buffer[size++] = pitch; + buffer[size++] = volume; + break; + case TEMPO: + code = 0xFF; + size += writeVarLength(time, buffer+size); + buffer[size++] = code; + buffer[size++] = 0x51; + buffer[size++] = 0x03; + writeBigEndian4(int(60000000.0 / tempo), fourbytes); + + //printf("tempo of %x translates to ", tempo); + for (int i=0; i<3; i++) printf("%02x ", fourbytes[i+1]); + printf("\n"); + buffer[size++] = fourbytes[1]; + buffer[size++] = fourbytes[2]; + buffer[size++] = fourbytes[3]; + break; + case PROG_CHANGE: + code = 0xC << 4 | channel; + size += writeVarLength(time, buffer+size); + buffer[size++] = code; + buffer[size++] = programNumber; + break; + case TRACK_NAME: + size += writeVarLength(time, buffer+size); + buffer[size++] = 0xFF; + buffer[size++] = 0x03; + size += writeVarLength(trackName.size(), buffer+size); + trackName.copy((char *)(&buffer[size]), trackName.size()); + size += trackName.size(); +// buffer[size++] = '\0'; +// buffer[size++] = '\0'; + + break; + } + return size; + } // writeEventsToBuffer + + + // events are sorted by their time + inline bool operator < (const Event& b) const { + return this->time < b.time; + } +}; + +template +class MIDITrack +{ + // A class that encapsulates a MIDI track + // Nested class definitions. + vector events; + + public: + uint8_t channel; + + MIDITrack(): channel(0) {} + + inline void addEvent(const Event &e) + { + Event E = e; + events.push_back(E); + } + + inline void addNote(uint8_t pitch, uint8_t volume, double time, double duration) + { + Event event; event.channel = channel; + event.volume = volume; + + event.type = Event::NOTE_ON; event.pitch = pitch; event.time= (uint32_t) (time * TICKSPERBEAT); + addEvent(event); + + event.type = Event::NOTE_OFF; event.pitch = pitch; event.time=(uint32_t) ((time+duration) * TICKSPERBEAT); + addEvent(event); + + //printf("note: %d-%d\n", (uint32_t) time * TICKSPERBEAT, (uint32_t)((time+duration) * TICKSPERBEAT)); + } + + inline void addName(const string &name, uint32_t time) + { + Event event; event.channel = channel; + event.type = Event::TRACK_NAME; event.time=time; event.trackName = name; + addEvent(event); + } + + inline void addProgramChange(uint8_t prog, uint32_t time) + { + Event event; event.channel = channel; + event.type = Event::PROG_CHANGE; event.time=time; event.programNumber = prog; + addEvent(event); + } + + inline void addTempo(uint8_t tempo, uint32_t time) + { + Event event; event.channel = channel; + event.type = Event::TEMPO; event.time=time; event.tempo = tempo; + addEvent(event); + } + + inline int writeMIDIToBuffer(uint8_t *buffer, int start=0) const + { + // Write the meta data and note data to the packed MIDI stream. + // Process the events in the eventList + + start += writeEventsToBuffer(buffer, start); + + // Write MIDI close event. + buffer[start++] = 0x00; + buffer[start++] = 0xFF; + buffer[start++] = 0x2F; + buffer[start++] = 0x00; + + // return the entire length of the data and write to the header + + return start; + } + + inline int writeEventsToBuffer(uint8_t *buffer, int start=0) const + { + // Write the events in MIDIEvents to the MIDI stream. + vector _events = events; + std::sort(_events.begin(), _events.end()); + vector::const_iterator it; + uint32_t time_last = 0, tmp; + for (it = _events.begin(); it!=_events.end(); ++it) + { + Event e = *it; + if (e.time < time_last){ + printf("error: e.time=%d time_last=%d\n", e.time, time_last); + assert(false); + } + tmp = e.time; + e.time -= time_last; + time_last = tmp; + start += e.writeToBuffer(buffer+start); + if (start >= MAX_TRACK_SIZE) { + break; + } + } + return start; + } + + inline int writeToBuffer(uint8_t *buffer, int start=0) const + { + uint8_t eventsBuffer[MAX_TRACK_SIZE]; + uint32_t events_size = writeMIDIToBuffer(eventsBuffer); + //printf(">> track %lu events took 0x%x bytes\n", events.size(), events_size); + + // chunk ID + buffer[start++] = 'M'; buffer[start++] = 'T'; buffer[start++] = 'r'; buffer[start++] = 'k'; + // chunk size + start += writeBigEndian4(events_size, buffer+start); + // copy events data + memmove(buffer+start, eventsBuffer, events_size); + start += events_size; + return start; + } +}; + +}; // namespace + +#endif diff --git a/plugins/MidiImport/MidiImport.cpp b/plugins/MidiImport/MidiImport.cpp index ec3178d85..67e7ba3b4 100644 --- a/plugins/MidiImport/MidiImport.cpp +++ b/plugins/MidiImport/MidiImport.cpp @@ -497,6 +497,15 @@ bool MidiImport::readSMF( TrackContainer* tc ) } } + // Set channel 10 to drums as per General MIDI's orders + if( chs[9].hasNotes && chs[9].it_inst && chs[9].isSF2 ) + { + // AFAIK, 128 should be the standard bank for drums in SF2. + // If not, this has to be made configurable. + chs[9].it_inst->childModel( "bank" )->setValue( 128 ); + chs[9].it_inst->childModel( "patch" )->setValue( 0 ); + } + return true; } diff --git a/plugins/delay/CMakeLists.txt b/plugins/delay/CMakeLists.txt deleted file mode 100644 index 0663b9458..000000000 --- a/plugins/delay/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -INCLUDE(BuildPlugin) - -BUILD_PLUGIN(delay delayeffect.cpp delaycontrols.cpp delaycontrolsdialog.cpp lfo.cpp stereodelay.cpp MOCFILES delaycontrols.h EMBEDDED_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.png") diff --git a/plugins/delay/artwork.png b/plugins/delay/artwork.png deleted file mode 100644 index 459c1c544..000000000 Binary files a/plugins/delay/artwork.png and /dev/null differ diff --git a/plugins/lb302/lb302.cpp b/plugins/lb302/lb302.cpp index 14ecb8fa1..5864b94c8 100644 --- a/plugins/lb302/lb302.cpp +++ b/plugins/lb302/lb302.cpp @@ -458,10 +458,6 @@ void lb302Synth::recalcFilter() vcf_envpos = ENVINC; // Trigger filter update in process() } -inline int MIN(int a, int b) { - return (aprocessingSampleRate(); // TODO: Use actual sampling rate. } diff --git a/plugins/triple_oscillator/TripleOscillator.cpp b/plugins/triple_oscillator/TripleOscillator.cpp index cdb35606c..b984d10da 100644 --- a/plugins/triple_oscillator/TripleOscillator.cpp +++ b/plugins/triple_oscillator/TripleOscillator.cpp @@ -581,7 +581,7 @@ TripleOscillatorView::TripleOscillatorView( Instrument * _instrument, ck->setWhatsThis( tr( "With this knob you can set the coarse detuning of " "oscillator %1. You can detune the oscillator " - "12 semitones (1 octave) up and down. This is " + "24 semitones (2 octaves) up and down. This is " "useful for creating sounds with a chord." ). arg( i + 1 ) ); diff --git a/plugins/waveshaper/waveshaper.cpp b/plugins/waveshaper/waveshaper.cpp index 7389e27e1..33300a32d 100644 --- a/plugins/waveshaper/waveshaper.cpp +++ b/plugins/waveshaper/waveshaper.cpp @@ -82,18 +82,27 @@ bool waveShaperEffect::processAudioBuffer( sampleFrame * _buf, double out_sum = 0.0; const float d = dryLevel(); const float w = wetLevel(); - const float input = m_wsControls.m_inputModel.value(); - const float output = m_wsControls.m_outputModel.value(); + float input = m_wsControls.m_inputModel.value(); + float output = m_wsControls.m_outputModel.value(); const float * samples = m_wsControls.m_wavegraphModel.samples(); const bool clip = m_wsControls.m_clipModel.value(); + ValueBuffer *inputBuffer = m_wsControls.m_inputModel.valueBuffer(); + ValueBuffer *outputBufer = m_wsControls.m_outputModel.valueBuffer(); + + int inputInc = inputBuffer ? 1 : 0; + int outputInc = outputBufer ? 1 : 0; + + float *inputPtr = inputBuffer ? &( inputBuffer->values()[ 0 ] ) : &input; + float *outputPtr = outputBufer ? &( outputBufer->values()[ 0 ] ) : &output; + for( fpp_t f = 0; f < _frames; ++f ) { float s[2] = { _buf[f][0], _buf[f][1] }; // apply input gain - s[0] *= input; - s[1] *= input; + s[0] *= *inputPtr; + s[1] *= *inputPtr; // clip if clip enabled if( clip ) @@ -127,13 +136,16 @@ bool waveShaperEffect::processAudioBuffer( sampleFrame * _buf, } // apply output gain - s[0] *= output; - s[1] *= output; + s[0] *= *outputPtr; + s[1] *= *outputPtr; out_sum += _buf[f][0]*_buf[f][0] + _buf[f][1]*_buf[f][1]; // mix wet/dry signals _buf[f][0] = d * _buf[f][0] + w * s[0]; _buf[f][1] = d * _buf[f][1] + w * s[1]; + + outputPtr += outputInc; + inputPtr += inputInc; } checkGate( out_sum / _frames ); diff --git a/plugins/zynaddsubfx/CMakeLists.txt b/plugins/zynaddsubfx/CMakeLists.txt index af575f82b..b469351f8 100644 --- a/plugins/zynaddsubfx/CMakeLists.txt +++ b/plugins/zynaddsubfx/CMakeLists.txt @@ -32,7 +32,11 @@ IF(MINGW_PREFIX) SET(FLTK_SKIP_FLUID TRUE) ENDIF() -FIND_PACKAGE(FLTK REQUIRED) +FIND_PACKAGE(FLTK) + +IF(NOT FLTK_FOUND) + RETURN() +ENDIF() IF(MINGW_PREFIX) SET(FLTK_FLUID_EXECUTABLE "${MINGW_PREFIX}/bin/fluid") diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d0f8760a1..2dd80421a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -176,7 +176,7 @@ IF(LMMS_BUILD_WIN32) "${MINGW_PREFIX}/bin/libvorbisfile-3.dll" "${MINGW_PREFIX}/bin/libjpeg-9.dll" "${MINGW_PREFIX}/bin/libogg-0.dll" - "${MINGW_PREFIX}/lib/libfltk.dll" + "${MINGW_PREFIX}/bin/libfltk.dll" "${MINGW_PREFIX}/bin/libfluidsynth.dll" "${MINGW_PREFIX}/bin/libfftw3f-3.dll" "${MINGW_PREFIX}/bin/libFLAC-8.dll" diff --git a/src/core/AutomatableModel.cpp b/src/core/AutomatableModel.cpp index 6c7501c8b..bf56285e5 100644 --- a/src/core/AutomatableModel.cpp +++ b/src/core/AutomatableModel.cpp @@ -318,8 +318,7 @@ void AutomatableModel::setAutomatedValue( const float value ) it != m_linkedModels.end(); ++it ) { if( (*it)->m_setValueDepth < 1 && - !(*it)->fittedValue( m_value ) != - (*it)->m_value ) + (*it)->fittedValue( m_value ) != (*it)->m_value ) { (*it)->setAutomatedValue( value ); } diff --git a/src/core/AutomationPattern.cpp b/src/core/AutomationPattern.cpp index 4c8791ee3..f14e6cb70 100644 --- a/src/core/AutomationPattern.cpp +++ b/src/core/AutomationPattern.cpp @@ -519,6 +519,7 @@ void AutomationPattern::saveSettings( QDomDocument & _doc, QDomElement & _this ) _this.setAttribute( "name", name() ); _this.setAttribute( "prog", QString::number( progressionType() ) ); _this.setAttribute( "tens", QString::number( getTension() ) ); + _this.setAttribute( "mute", QString::number( isMuted() ) ); for( timeMap::const_iterator it = m_timeMap.begin(); it != m_timeMap.end(); ++it ) @@ -553,6 +554,7 @@ void AutomationPattern::loadSettings( const QDomElement & _this ) setProgressionType( static_cast( _this.attribute( "prog" ).toInt() ) ); setTension( _this.attribute( "tens" ) ); + setMuted(_this.attribute( "mute", QString::number( false ) ).toInt() ); for( QDomNode node = _this.firstChild(); !node.isNull(); node = node.nextSibling() ) diff --git a/src/core/ConfigManager.cpp b/src/core/ConfigManager.cpp index 2f5c29001..81fb9022c 100644 --- a/src/core/ConfigManager.cpp +++ b/src/core/ConfigManager.cpp @@ -28,9 +28,9 @@ #include #include -#include "lmmsversion.h" #include "ConfigManager.h" #include "MainWindow.h" +#include "ProjectVersion.h" static inline QString ensureTrailingSlash( const QString & _s ) @@ -61,7 +61,7 @@ ConfigManager::ConfigManager() : m_artworkDir( defaultArtworkDir() ), m_vstDir( m_workingDir + "vst" + QDir::separator() ), m_flDir( QDir::home().absolutePath() ), - m_recoveryFile( QDir(m_workingDir).absoluteFilePath("recover.mmp") ) + m_version( defaultVersion() ) { if (! qgetenv("LMMS_DATA_DIR").isEmpty()) QDir::addSearchPath("data", QString::fromLocal8Bit(qgetenv("LMMS_DATA_DIR"))); @@ -79,6 +79,36 @@ ConfigManager::~ConfigManager() +void ConfigManager::upgrade() +{ + // Skip the upgrade if versions match + if ( m_version == LMMS_VERSION ) + { + return; + } + + ProjectVersion createdWith = m_version; + + // Remove trailing " (bad latency!)" string which was once saved with PulseAudio + if ( createdWith.setCompareType(Build) < "1.1.90" ) + { + if( value( "mixer", "audiodev" ).startsWith( "PulseAudio (" ) ) + { + setValue("mixer", "audiodev", "PulseAudio"); + } + } + + // Don't use old themes as they break the UI (i.e. 0.4 != 1.0, etc) + if ( createdWith.setCompareType(Minor) != LMMS_VERSION ) + { + m_artworkDir = defaultArtworkDir(); + } + + // Bump the version, now that we are upgraded + m_version = LMMS_VERSION; +} + + void ConfigManager::setWorkingDir( const QString & _wd ) { m_workingDir = ensureTrailingSlash( _wd ); @@ -249,6 +279,11 @@ void ConfigManager::loadConfigFile() QDomNode node = root.firstChild(); + // Cache the config version for upgrade() + if ( !root.attribute( "version" ).isNull() ) { + m_version = root.attribute( "version" ); + } + // create the settings-map out of the DOM while( !node.isNull() ) { @@ -287,13 +322,7 @@ void ConfigManager::loadConfigFile() node = node.nextSibling(); } - // don't use dated theme folders as they break the UI (i.e. 0.4 != 1.0, etc) - bool use_artwork_path = - root.attribute( "version" ).startsWith( - QString::number( LMMS_VERSION_MAJOR ) + "." + - QString::number( LMMS_VERSION_MINOR ) ); - - if( use_artwork_path && value( "paths", "artwork" ) != "" ) + if( value( "paths", "artwork" ) != "" ) { m_artworkDir = value( "paths", "artwork" ); if( !QDir( m_artworkDir ).exists() ) @@ -396,6 +425,8 @@ void ConfigManager::loadConfigFile() QDir().mkpath( userSamplesDir() ); QDir().mkpath( userPresetsDir() ); } + + upgrade(); } @@ -419,7 +450,7 @@ void ConfigManager::saveConfigFile() QDomDocument doc( "lmms-config-file" ); QDomElement lmms_config = doc.createElement( "lmms" ); - lmms_config.setAttribute( "version", LMMS_VERSION ); + lmms_config.setAttribute( "version", m_version ); doc.appendChild( lmms_config ); for( settingsMap::iterator it = m_settings.begin(); diff --git a/src/core/DataFile.cpp b/src/core/DataFile.cpp index 8db694367..d2e76aab7 100644 --- a/src/core/DataFile.cpp +++ b/src/core/DataFile.cpp @@ -36,6 +36,7 @@ #include "ConfigManager.h" +#include "PluginFactory.h" #include "ProjectVersion.h" #include "ProjectVersion.h" #include "SongEditor.h" @@ -163,6 +164,53 @@ DataFile::~DataFile() +bool DataFile::validate( QString extension ) +{ + switch( m_type ) + { + case Type::SongProject: + if( extension == "mmp" || extension == "mmpz" ) + { + return true; + } + break; + case Type::SongProjectTemplate: + if( extension == "mpt" ) + { + return true; + } + break; + case Type::InstrumentTrackSettings: + if ( extension == "xpf" || extension == "xml" ) + { + return true; + } + break; + case Type::UnknownType: + if (! ( extension == "mmp" || extension == "mpt" || extension == "mmpz" || + extension == "xpf" || extension == "xml" || + ( extension == "xiz" && ! pluginFactory->pluginSupportingExtension(extension).isNull()) || + extension == "sf2" || extension == "pat" || extension == "mid" || + extension == "flp" || extension == "dll" + ) ) + { + return true; + } + if( extension == "wav" || extension == "ogg" || + extension == "ds" ) + { + return true; + } + break; + default: + return false; + } + return false; +} + + + + QString DataFile::nameWithExtension( const QString & _fn ) const { switch( type() ) @@ -804,14 +852,17 @@ void DataFile::loadData( const QByteArray & _data, const QString & _sourceFile ) // only one compareType needs to be set, and we can compare on one line because setCompareType returns ProjectVersion if ( createdWith.setCompareType(Minor) != openedWith) { - if( Engine::hasGUI() ) + if( Engine::hasGUI() && root.attribute( "type" ) == "song" ) //documentElement() { QMessageBox::information( NULL, SongEditor::tr( "Project Version Mismatch" ), SongEditor::tr( - "This project was created with " - "LMMS version %1, but version %2 " + "This %1 was created with " + "LMMS version %2, but version %3 " "is installed") + .arg( _sourceFile.endsWith( ".mpt" ) ? + "template" : + "project" ) .arg( root.attribute( "creatorversion" ) ) .arg( LMMS_VERSION ) ); } diff --git a/src/core/LfoController.cpp b/src/core/LfoController.cpp index f7c65a752..e1b20a492 100644 --- a/src/core/LfoController.cpp +++ b/src/core/LfoController.cpp @@ -98,6 +98,10 @@ void LfoController::updateValueBuffer() m_bufferLastUpdated += diff; } + float amount = m_amountModel.value(); + ValueBuffer *amountBuffer = m_amountModel.valueBuffer(); + int amountInc = amountBuffer ? 1 : 0; + float *amountPtr = amountBuffer ? &(amountBuffer->values()[ 0 ] ) : &amount; for( int i = 0; i < m_valueBuffer.length(); i++ ) { @@ -105,15 +109,15 @@ void LfoController::updateValueBuffer() ? m_sampleFunction( phase ) : m_userDefSampleBuffer->userWaveSample( phase ); - values[i] = qBound( 0.0f, m_baseModel.value() + ( m_amountModel.value() * currentSample / 2.0f ), 1.0f ); + values[i] = qBound( 0.0f, m_baseModel.value() + ( *amountPtr * currentSample / 2.0f ), 1.0f ); phase += 1.0 / m_duration; + amountPtr += amountInc; } m_currentPhase = absFraction( phase - m_phaseOffset ); } - void LfoController::updatePhase() { m_currentPhase = ( Engine::getSong()->getFrames() ) / m_duration; diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index ba8006ddd..845abbf93 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -315,9 +315,9 @@ const surroundSampleFrame * Mixer::renderNextBuffer() { m_profiler.startPeriod(); - static Song::playPos last_metro_pos = -1; + static Song::PlayPos last_metro_pos = -1; - Song::playPos p = Engine::getSong()->getPlayPos( + Song::PlayPos p = Engine::getSong()->getPlayPos( Song::Mode_PlayPattern ); if( Engine::getSong()->playMode() == Song::Mode_PlayPattern && gui->pianoRoll()->isRecording() == true && @@ -965,6 +965,3 @@ void Mixer::fifoWriter::run() - - - diff --git a/src/core/Note.cpp b/src/core/Note.cpp index fb76a491c..f5851dde4 100644 --- a/src/core/Note.cpp +++ b/src/core/Note.cpp @@ -2,7 +2,7 @@ * note.cpp - implementation of class note * * Copyright (c) 2004-2014 Tobias Doerffel - * + * * This file is part of LMMS - http://lmms.io * * This program is free software; you can redistribute it and/or @@ -29,28 +29,30 @@ #include "Note.h" #include "DetuningHelper.h" +#include "templates.h" -Note::Note( const MidiTime & _length, const MidiTime & _pos, - int _key, volume_t _volume, panning_t _panning, - DetuningHelper * _detuning ) : + +Note::Note( const MidiTime & length, const MidiTime & pos, + int key, volume_t volume, panning_t panning, + DetuningHelper * detuning ) : m_selected( false ), - m_oldKey( qBound( 0, _key, NumKeys ) ), - m_oldPos( _pos ), - m_oldLength( _length ), + m_oldKey( qBound( 0, key, NumKeys ) ), + m_oldPos( pos ), + m_oldLength( length ), m_isPlaying( false ), - m_key( qBound( 0, _key, NumKeys ) ), - m_volume( qBound( MinVolume, _volume, MaxVolume ) ), - m_panning( qBound( PanningLeft, _panning, PanningRight ) ), - m_length( _length ), - m_pos( _pos ), + m_key( qBound( 0, key, NumKeys ) ), + m_volume( qBound( MinVolume, volume, MaxVolume ) ), + m_panning( qBound( PanningLeft, panning, PanningRight ) ), + m_length( length ), + m_pos( pos ), m_detuning( NULL ) { - if( _detuning ) + if( detuning ) { - m_detuning = sharedObject::ref( _detuning ); + m_detuning = sharedObject::ref( detuning ); } else { @@ -61,23 +63,23 @@ Note::Note( const MidiTime & _length, const MidiTime & _pos, -Note::Note( const Note & _note ) : - SerializingObject( _note ), - m_selected( _note.m_selected ), - m_oldKey( _note.m_oldKey ), - m_oldPos( _note.m_oldPos ), - m_oldLength( _note.m_oldLength ), - m_isPlaying( _note.m_isPlaying ), - m_key( _note.m_key), - m_volume( _note.m_volume ), - m_panning( _note.m_panning ), - m_length( _note.m_length ), - m_pos( _note.m_pos ), +Note::Note( const Note & note ) : + SerializingObject( note ), + m_selected( note.m_selected ), + m_oldKey( note.m_oldKey ), + m_oldPos( note.m_oldPos ), + m_oldLength( note.m_oldLength ), + m_isPlaying( note.m_isPlaying ), + m_key( note.m_key), + m_volume( note.m_volume ), + m_panning( note.m_panning ), + m_length( note.m_length ), + m_pos( note.m_pos ), m_detuning( NULL ) { - if( _note.m_detuning ) + if( note.m_detuning ) { - m_detuning = sharedObject::ref( _note.m_detuning ); + m_detuning = sharedObject::ref( note.m_detuning ); } } @@ -95,93 +97,93 @@ Note::~Note() -void Note::setLength( const MidiTime & _length ) +void Note::setLength( const MidiTime & length ) { - m_length = _length; + m_length = length; } -void Note::setPos( const MidiTime & _pos ) +void Note::setPos( const MidiTime & pos ) { - m_pos = _pos; + m_pos = pos; } -void Note::setKey( const int _key ) +void Note::setKey( const int key ) { - const int k = qBound( 0, _key, NumKeys ); + const int k = qBound( 0, key, NumKeys ); m_key = k; } -void Note::setVolume( volume_t _volume ) +void Note::setVolume( volume_t volume ) { - const volume_t v = qBound( MinVolume, _volume, MaxVolume ); + const volume_t v = qBound( MinVolume, volume, MaxVolume ); m_volume = v; } -void Note::setPanning( panning_t _panning ) +void Note::setPanning( panning_t panning ) { - const panning_t p = qBound( PanningLeft, _panning, PanningRight ); + const panning_t p = qBound( PanningLeft, panning, PanningRight ); m_panning = p; } -MidiTime Note::quantized( const MidiTime & _m, const int _q_grid ) +MidiTime Note::quantized( const MidiTime & m, const int qGrid ) { - float p = ( (float) _m / _q_grid ); + float p = ( (float) m / qGrid ); if( p - floorf( p ) < 0.5f ) { - return( static_cast( p ) * _q_grid ); + return static_cast( p ) * qGrid; } - return( static_cast( p + 1 ) * _q_grid ); + return static_cast( p + 1 ) * qGrid; } -void Note::quantizeLength( const int _q_grid ) +void Note::quantizeLength( const int qGrid ) { - setLength( quantized( length(), _q_grid ) ); + setLength( quantized( length(), qGrid ) ); if( length() == 0 ) { - setLength( _q_grid ); + setLength( qGrid ); } } -void Note::quantizePos( const int _q_grid ) +void Note::quantizePos( const int qGrid ) { - setPos( quantized( pos(), _q_grid ) ); + setPos( quantized( pos(), qGrid ) ); } -void Note::saveSettings( QDomDocument & _doc, QDomElement & _this ) +void Note::saveSettings( QDomDocument & doc, QDomElement & parent ) { - _this.setAttribute( "key", m_key ); - _this.setAttribute( "vol", m_volume ); - _this.setAttribute( "pan", m_panning ); - _this.setAttribute( "len", m_length ); - _this.setAttribute( "pos", m_pos ); + parent.setAttribute( "key", m_key ); + parent.setAttribute( "vol", m_volume ); + parent.setAttribute( "pan", m_panning ); + parent.setAttribute( "len", m_length ); + parent.setAttribute( "pos", m_pos ); if( m_detuning && m_length ) { - m_detuning->saveSettings( _doc, _this ); + m_detuning->saveSettings( doc, parent ); } } @@ -229,4 +231,8 @@ bool Note::hasDetuningInfo() const - +bool Note::withinRange(int tickStart, int tickEnd) const +{ + return pos().getTicks() >= tickStart && pos().getTicks() <= tickEnd + && length().getTicks() != 0; +} diff --git a/src/core/Plugin.cpp b/src/core/Plugin.cpp index 729fb11c0..f6409ef2d 100644 --- a/src/core/Plugin.cpp +++ b/src/core/Plugin.cpp @@ -38,9 +38,9 @@ #include "Song.h" -static PixmapLoader __dummy_loader; +static PixmapLoader __dummyLoader; -static Plugin::Descriptor dummy_plugin_descriptor = +static Plugin::Descriptor dummyPluginDescriptor = { "dummy", "dummy", @@ -48,21 +48,21 @@ static Plugin::Descriptor dummy_plugin_descriptor = "Tobias Doerffel ", 0x0100, Plugin::Undefined, - &__dummy_loader, + &__dummyLoader, NULL } ; -Plugin::Plugin( const Descriptor * _descriptor, Model * parent ) : +Plugin::Plugin( const Descriptor * descriptor, Model * parent ) : Model( parent ), JournallingObject(), - m_descriptor( _descriptor ) + m_descriptor( descriptor ) { if( m_descriptor == NULL ) { - m_descriptor = &dummy_plugin_descriptor; + m_descriptor = &dummyPluginDescriptor; } } @@ -126,13 +126,17 @@ Plugin * Plugin::instantiate( const QString& pluginName, Model * parent, return inst; } -void Plugin::collectErrorForUI( QString err_msg ) + + + +void Plugin::collectErrorForUI( QString errMsg ) { - Engine::getSong()->collectError( err_msg ); + Engine::getSong()->collectError( errMsg ); } + PluginView * Plugin::createView( QWidget * parent ) { PluginView * pv = instantiateView( parent ); @@ -145,13 +149,13 @@ PluginView * Plugin::createView( QWidget * parent ) -Plugin::Descriptor::SubPluginFeatures::Key::Key( - const QDomElement & _key ) : + +Plugin::Descriptor::SubPluginFeatures::Key::Key( const QDomElement & key ) : desc( NULL ), - name( _key.attribute( "key" ) ), + name( key.attribute( "key" ) ), attributes() { - QDomNodeList l = _key.elementsByTagName( "attribute" ); + QDomNodeList l = key.elementsByTagName( "attribute" ); for( int i = 0; !l.item( i ).isNull(); ++i ) { QDomElement e = l.item( i ).toElement(); @@ -164,13 +168,13 @@ Plugin::Descriptor::SubPluginFeatures::Key::Key( QDomElement Plugin::Descriptor::SubPluginFeatures::Key::saveXML( - QDomDocument & _doc ) const + QDomDocument & doc ) const { - QDomElement e = _doc.createElement( "key" ); - for( AttributeMap::ConstIterator it = attributes.begin(); - it != attributes.end(); ++it ) + QDomElement e = doc.createElement( "key" ); + for( AttributeMap::ConstIterator it = attributes.begin(); + it != attributes.end(); ++it ) { - QDomElement a = _doc.createElement( "attribute" ); + QDomElement a = doc.createElement( "attribute" ); a.setAttribute( "name", it.key() ); a.setAttribute( "value", it.value() ); e.appendChild( a ); @@ -178,3 +182,5 @@ QDomElement Plugin::Descriptor::SubPluginFeatures::Key::saveXML( return e; } + + diff --git a/src/core/PresetPreviewPlayHandle.cpp b/src/core/PresetPreviewPlayHandle.cpp index 4282b29a2..4b8b49970 100644 --- a/src/core/PresetPreviewPlayHandle.cpp +++ b/src/core/PresetPreviewPlayHandle.cpp @@ -112,7 +112,7 @@ PreviewTrackContainer * PresetPreviewPlayHandle::s_previewTC; -PresetPreviewPlayHandle::PresetPreviewPlayHandle( const QString & _preset_file, bool _load_by_plugin ) : +PresetPreviewPlayHandle::PresetPreviewPlayHandle( const QString & _preset_file, bool _load_by_plugin, DataFile *dataFile ) : PlayHandle( TypePresetPreviewHandle ), m_previewNote( NULL ) { @@ -144,22 +144,32 @@ PresetPreviewPlayHandle::PresetPreviewPlayHandle( const QString & _preset_file, } else { - DataFile dataFile( _preset_file ); + bool dataFileCreated = false; + if( dataFile == 0 ) + { + dataFile = new DataFile( _preset_file ); + dataFileCreated = true; + } + // vestige previews are bug prone; fallback on 3xosc with volume of 0 // without an instrument in preview track, it will segfault - if(dataFile.content().elementsByTagName( "vestige" ).length() == 0 ) + if(dataFile->content().elementsByTagName( "vestige" ).length() == 0 ) { s_previewTC->previewInstrumentTrack()-> loadTrackSpecificSettings( - dataFile.content().firstChild().toElement() ); + dataFile->content().firstChild().toElement() ); } else { s_previewTC->previewInstrumentTrack()->loadInstrument("tripleoscillator"); s_previewTC->previewInstrumentTrack()->setVolume( 0 ); } + if( dataFileCreated ) + { + delete dataFile; + } } - + dataFile = 0; // make sure, our preset-preview-track does not appear in any MIDI- // devices list, so just disable receiving/sending MIDI-events at all s_previewTC->previewInstrumentTrack()-> diff --git a/src/core/ProjectRenderer.cpp b/src/core/ProjectRenderer.cpp index 727cb630c..e8a91c77d 100644 --- a/src/core/ProjectRenderer.cpp +++ b/src/core/ProjectRenderer.cpp @@ -163,7 +163,7 @@ void ProjectRenderer::run() //skip first empty buffer Engine::mixer()->nextBuffer(); - Song::playPos & pp = Engine::getSong()->getPlayPos( + Song::PlayPos & pp = Engine::getSong()->getPlayPos( Song::Mode_PlaySong ); m_progress = 0; const int sl = ( Engine::getSong()->length() + 1 ) * 192; @@ -230,5 +230,3 @@ void ProjectRenderer::updateConsoleProgress() - - diff --git a/src/core/ProjectVersion.cpp b/src/core/ProjectVersion.cpp index 7fc602c67..111e014a8 100644 --- a/src/core/ProjectVersion.cpp +++ b/src/core/ProjectVersion.cpp @@ -31,18 +31,30 @@ int parseMajor(QString & version) { return version.section( '.', 0, 0 ).toInt(); } + + + int parseMinor(QString & version) { return version.section( '.', 1, 1 ).toInt(); } + + + int parseRelease(QString & version) { return version.section( '.', 2 ).section( '-', 0, 0 ).toInt(); } + + + QString parseBuild(QString & version) { return version.section( '.', 2 ).section( '-', 1 ); } + + + ProjectVersion::ProjectVersion(QString version, CompareType c) : m_version(version), m_major(parseMajor(m_version)), @@ -53,41 +65,48 @@ ProjectVersion::ProjectVersion(QString version, CompareType c) : { } + + + ProjectVersion::ProjectVersion(const char* version, CompareType c) : m_version(QString(version)), m_major(parseMajor(m_version)), m_minor(parseMinor(m_version)), - m_release(parseRelease(m_version)) , + m_release(parseRelease(m_version)), m_build(parseBuild(m_version)), m_compareType(c) { } -int ProjectVersion::compare(const ProjectVersion& a, const ProjectVersion& b, CompareType c) + + + +int ProjectVersion::compare(const ProjectVersion & a, const ProjectVersion & b, CompareType c) { - if (a.getMajor() != b.getMajor()) + if(a.getMajor() != b.getMajor()) { return a.getMajor() - b.getMajor(); } - else if (c == CompareType::Major) + + else if(c == CompareType::Major) { return 0; } - if (a.getMinor() != b.getMinor()) + if(a.getMinor() != b.getMinor()) { return a.getMinor() - b.getMinor(); } - else if (c == CompareType::Minor) + else if(c == CompareType::Minor) { return 0; } - if (a.getRelease() != b.getRelease()) + if(a.getRelease() != b.getRelease()) { return a.getRelease() - b.getRelease(); } - else if (c == CompareType::Release) + else if(c == CompareType::Release) { return 0; } @@ -105,8 +124,13 @@ int ProjectVersion::compare(const ProjectVersion& a, const ProjectVersion& b, Co return QString::compare(a.getBuild(), b.getBuild()); } + + + int ProjectVersion::compare(ProjectVersion v1, ProjectVersion v2) { return compare(v1, v2, std::min(v1.getCompareType(), v2.getCompareType())); } + + diff --git a/src/core/Song.cpp b/src/core/Song.cpp index 7198416cc..0f688a1b1 100644 --- a/src/core/Song.cpp +++ b/src/core/Song.cpp @@ -47,6 +47,7 @@ #include "FxMixerView.h" #include "GuiApplication.h" #include "ImportFilter.h" +#include "ExportFilter.h" #include "InstrumentTrack.h" #include "MainWindow.h" #include "FileDialog.h" @@ -144,7 +145,7 @@ void Song::masterVolumeChanged() void Song::setTempo() { Engine::mixer()->lockPlayHandleRemoval(); - const bpm_t tempo = (bpm_t) m_tempoModel.value(); + const bpm_t tempo = ( bpm_t ) m_tempoModel.value(); PlayHandleList & playHandles = Engine::mixer()->playHandles(); for( PlayHandleList::Iterator it = playHandles.begin(); it != playHandles.end(); ++it ) @@ -176,7 +177,8 @@ void Song::setTimeSignature() emit dataChanged(); m_oldTicksPerTact = ticksPerTact(); - m_vstSyncController.setTimeSignature( getTimeSigModel().getNumerator(), getTimeSigModel().getDenominator() ); + m_vstSyncController.setTimeSignature( + getTimeSigModel().getNumerator(), getTimeSigModel().getDenominator() ); } @@ -202,13 +204,13 @@ void Song::processNextBuffer() return; } - TrackList track_list; - int tco_num = -1; + TrackList trackList; + int tcoNum = -1; switch( m_playMode ) { case Mode_PlaySong: - track_list = tracks(); + trackList = tracks(); // at song-start we have to reset the LFOs if( m_playPos[Mode_PlaySong] == 0 ) { @@ -217,25 +219,25 @@ void Song::processNextBuffer() break; case Mode_PlayTrack: - track_list.push_back( m_trackToPlay ); + trackList.push_back( m_trackToPlay ); break; case Mode_PlayBB: if( Engine::getBBTrackContainer()->numOfBBs() > 0 ) { - tco_num = Engine::getBBTrackContainer()-> + tcoNum = Engine::getBBTrackContainer()-> currentBB(); - track_list.push_back( BBTrack::findBBTrack( - tco_num ) ); + trackList.push_back( BBTrack::findBBTrack( + tcoNum ) ); } break; case Mode_PlayPattern: if( m_patternToPlay != NULL ) { - tco_num = m_patternToPlay->getTrack()-> + tcoNum = m_patternToPlay->getTrack()-> getTCONum( m_patternToPlay ); - track_list.push_back( + trackList.push_back( m_patternToPlay->getTrack() ); } break; @@ -245,41 +247,44 @@ void Song::processNextBuffer() } - if( track_list.empty() == true ) + if( trackList.empty() == true ) { return; } // check for looping-mode and act if necessary TimeLineWidget * tl = m_playPos[m_playMode].m_timeLine; - bool check_loop = tl != NULL && m_exporting == false && - tl->loopPointsEnabled(); - if( check_loop ) + bool checkLoop = + tl != NULL && m_exporting == false && tl->loopPointsEnabled(); + + if( checkLoop ) { if( m_playPos[m_playMode] < tl->loopBegin() || m_playPos[m_playMode] >= tl->loopEnd() ) { - m_elapsedMilliSeconds = (tl->loopBegin().getTicks()*60*1000/48)/getTempo(); + m_elapsedMilliSeconds = + ( tl->loopBegin().getTicks() * 60 * 1000 / 48 ) / getTempo(); m_playPos[m_playMode].setTicks( tl->loopBegin().getTicks() ); } } - f_cnt_t total_frames_played = 0; - const float frames_per_tick = Engine::framesPerTick(); + f_cnt_t totalFramesPlayed = 0; + const float framesPerTick = Engine::framesPerTick(); - while( total_frames_played - < Engine::mixer()->framesPerPeriod() ) + while( totalFramesPlayed < Engine::mixer()->framesPerPeriod() ) { m_vstSyncController.update(); - f_cnt_t played_frames = Engine::mixer()->framesPerPeriod() - total_frames_played; + f_cnt_t playedFrames = Engine::mixer()->framesPerPeriod() - + totalFramesPlayed; - float current_frame = m_playPos[m_playMode].currentFrame(); + float currentFrame = m_playPos[m_playMode].currentFrame(); // did we play a tick? - if( current_frame >= frames_per_tick ) + if( currentFrame >= framesPerTick ) { - int ticks = m_playPos[m_playMode].getTicks() + (int)( current_frame / frames_per_tick ); + int ticks = m_playPos[m_playMode].getTicks() + + ( int )( currentFrame / framesPerTick ); m_vstSyncController.setAbsolutePosition( ticks ); @@ -289,14 +294,14 @@ void Song::processNextBuffer() // per default we just continue playing even if // there's no more stuff to play // (song-play-mode) - int max_tact = m_playPos[m_playMode].getTact() + int maxTact = m_playPos[m_playMode].getTact() + 2; // then decide whether to go over to next tact // or to loop back to first tact if( m_playMode == Mode_PlayBB ) { - max_tact = Engine::getBBTrackContainer() + maxTact = Engine::getBBTrackContainer() ->lengthOfCurrentBB(); } else if( m_playMode == Mode_PlayPattern && @@ -304,34 +309,39 @@ void Song::processNextBuffer() tl != NULL && tl->loopPointsEnabled() == false ) { - max_tact = m_patternToPlay->length() + maxTact = m_patternToPlay->length() .getTact(); } // end of played object reached? if( m_playPos[m_playMode].getTact() + 1 - >= max_tact ) + >= maxTact ) { // then start from beginning and keep // offset - ticks = ticks % ( max_tact * MidiTime::ticksPerTact() ); + ticks %= ( maxTact * MidiTime::ticksPerTact() ); // wrap milli second counter - m_elapsedMilliSeconds = ( ticks * 60 * 1000 / 48 ) / getTempo(); + m_elapsedMilliSeconds = + ( ticks * 60 * 1000 / 48 ) / getTempo(); m_vstSyncController.setAbsolutePosition( ticks ); } } m_playPos[m_playMode].setTicks( ticks ); - if( check_loop ) + if( checkLoop ) { - m_vstSyncController.startCycle( tl->loopBegin().getTicks(), tl->loopEnd().getTicks() ); + m_vstSyncController.startCycle( + tl->loopBegin().getTicks(), tl->loopEnd().getTicks() ); if( m_playPos[m_playMode] >= tl->loopEnd() ) { m_playPos[m_playMode].setTicks( tl->loopBegin().getTicks() ); - m_elapsedMilliSeconds = ((tl->loopBegin().getTicks())*60*1000/48)/getTempo(); + + m_elapsedMilliSeconds = + ( ( tl->loopBegin().getTicks() ) * 60 * 1000 / 48 ) / + getTempo(); } } else @@ -339,55 +349,57 @@ void Song::processNextBuffer() m_vstSyncController.stopCycle(); } - current_frame = fmodf( current_frame, frames_per_tick ); - m_playPos[m_playMode].setCurrentFrame( current_frame ); + currentFrame = fmodf( currentFrame, framesPerTick ); + m_playPos[m_playMode].setCurrentFrame( currentFrame ); } - f_cnt_t last_frames = (f_cnt_t)frames_per_tick - - (f_cnt_t) current_frame; + f_cnt_t lastFrames = ( f_cnt_t )framesPerTick - + ( f_cnt_t )currentFrame; // skip last frame fraction - if( last_frames == 0 ) + if( lastFrames == 0 ) { - ++total_frames_played; - m_playPos[m_playMode].setCurrentFrame( current_frame + ++totalFramesPlayed; + m_playPos[m_playMode].setCurrentFrame( currentFrame + 1.0f ); continue; } // do we have some samples left in this tick but these are // less then samples we have to play? - if( last_frames < played_frames ) + if( lastFrames < playedFrames ) { // then set played_samples to remaining samples, the // rest will be played in next loop - played_frames = last_frames; + playedFrames = lastFrames; } - if( (f_cnt_t) current_frame == 0 ) + if( ( f_cnt_t ) currentFrame == 0 ) { if( m_playMode == Mode_PlaySong ) { m_globalAutomationTrack->play( m_playPos[m_playMode], - played_frames, - total_frames_played, tco_num ); + playedFrames, + totalFramesPlayed, tcoNum ); } // loop through all tracks and play them - for( int i = 0; i < track_list.size(); ++i ) + for( int i = 0; i < trackList.size(); ++i ) { - track_list[i]->play( m_playPos[m_playMode], - played_frames, - total_frames_played, tco_num ); + trackList[i]->play( m_playPos[m_playMode], + playedFrames, + totalFramesPlayed, tcoNum ); } } // update frame-counters - total_frames_played += played_frames; - m_playPos[m_playMode].setCurrentFrame( played_frames + - current_frame ); - m_elapsedMilliSeconds += (((played_frames/frames_per_tick)*60*1000/48)/getTempo()); + totalFramesPlayed += playedFrames; + m_playPos[m_playMode].setCurrentFrame( playedFrames + + currentFrame ); + m_elapsedMilliSeconds += + ( ( playedFrames / framesPerTick ) * 60 * 1000 / 48 ) + / getTempo(); m_elapsedTacts = m_playPos[Mode_PlaySong].getTact(); - m_elapsedTicks = (m_playPos[Mode_PlaySong].getTicks()%ticksPerTact())/48; + m_elapsedTicks = ( m_playPos[Mode_PlaySong].getTicks() % ticksPerTact() ) / 48; } } @@ -396,17 +408,21 @@ bool Song::isExportDone() const if ( m_renderBetweenMarkers ) { return m_exporting == true && - m_playPos[Mode_PlaySong].getTicks() >= m_playPos[Mode_PlaySong].m_timeLine->loopEnd().getTicks(); + m_playPos[Mode_PlaySong].getTicks() >= + m_playPos[Mode_PlaySong].m_timeLine->loopEnd().getTicks(); } + if( m_exportLoop) { return m_exporting == true && - m_playPos[Mode_PlaySong].getTicks() >= length() * ticksPerTact(); + m_playPos[Mode_PlaySong].getTicks() >= + length() * ticksPerTact(); } else { return m_exporting == true && - m_playPos[Mode_PlaySong].getTicks() >= ( length() + 1 ) * ticksPerTact(); + m_playPos[Mode_PlaySong].getTicks() >= + ( length() + 1 ) * ticksPerTact(); } } @@ -454,13 +470,13 @@ void Song::playAndRecord() -void Song::playTrack( Track * _trackToPlay ) +void Song::playTrack( Track * trackToPlay ) { if( isStopped() == false ) { stop(); } - m_trackToPlay = _trackToPlay; + m_trackToPlay = trackToPlay; m_playMode = Mode_PlayTrack; m_playing = true; @@ -497,7 +513,7 @@ void Song::playBB() -void Song::playPattern( const Pattern* patternToPlay, bool _loop ) +void Song::playPattern( const Pattern* patternToPlay, bool loop ) { if( isStopped() == false ) { @@ -505,7 +521,7 @@ void Song::playPattern( const Pattern* patternToPlay, bool _loop ) } m_patternToPlay = patternToPlay; - m_loopPattern = _loop; + m_loopPattern = loop; if( m_patternToPlay != NULL ) { @@ -543,12 +559,14 @@ void Song::updateLength() -void Song::setPlayPos( tick_t _ticks, PlayModes _play_mode ) +void Song::setPlayPos( tick_t ticks, PlayModes playMode ) { - m_elapsedTicks += m_playPos[_play_mode].getTicks() - _ticks; - m_elapsedMilliSeconds += (((( _ticks - m_playPos[_play_mode].getTicks()))*60*1000/48)/getTempo()); - m_playPos[_play_mode].setTicks( _ticks ); - m_playPos[_play_mode].setCurrentFrame( 0.0f ); + m_elapsedTicks += m_playPos[playMode].getTicks() - ticks; + m_elapsedMilliSeconds += + ( ( ( ( ticks - m_playPos[playMode].getTicks() ) ) * 60 * 1000 / 48) / + getTempo() ); + m_playPos[playMode].setTicks( ticks ); + m_playPos[playMode].setCurrentFrame( 0.0f ); // send a signal if playposition changes during playback if( isPlaying() ) @@ -608,7 +626,9 @@ void Song::stop() if( tl->savedPos() >= 0 ) { m_playPos[m_playMode].setTicks( tl->savedPos().getTicks() ); - m_elapsedMilliSeconds = (((tl->savedPos().getTicks())*60*1000/48)/getTempo()); + m_elapsedMilliSeconds = + ( ( ( tl->savedPos().getTicks() ) * 60 * 1000 / 48 ) / + getTempo() ); tl->savePos( -1 ); } break; @@ -713,7 +733,7 @@ void Song::addBBTrack() void Song::addSampleTrack() { - (void) Track::create( Track::SampleTrack, this ); + ( void )Track::create( Track::SampleTrack, this ); } @@ -721,7 +741,7 @@ void Song::addSampleTrack() void Song::addAutomationTrack() { - (void) Track::create( Track::AutomationTrack, this ); + ( void )Track::create( Track::AutomationTrack, this ); } @@ -729,7 +749,7 @@ void Song::addAutomationTrack() bpm_t Song::getTempo() { - return (bpm_t) m_tempoModel.value(); + return ( bpm_t )m_tempoModel.value(); } @@ -824,24 +844,23 @@ void Song::clearProject() - // create new file void Song::createNewProject() { - QString default_template = ConfigManager::inst()->userProjectsDir() + QString defaultTemplate = ConfigManager::inst()->userProjectsDir() + "templates/default.mpt"; - if( QFile::exists( default_template ) ) + if( QFile::exists( defaultTemplate ) ) { - createNewProjectFromTemplate( default_template ); + createNewProjectFromTemplate( defaultTemplate ); return; } - default_template = ConfigManager::inst()->factoryProjectsDir() + defaultTemplate = ConfigManager::inst()->factoryProjectsDir() + "templates/default.mpt"; - if( QFile::exists( default_template ) ) + if( QFile::exists( defaultTemplate ) ) { - createNewProjectFromTemplate( default_template ); + createNewProjectFromTemplate( defaultTemplate ); return; } @@ -891,9 +910,9 @@ void Song::createNewProject() -void Song::createNewProjectFromTemplate( const QString & _template ) +void Song::createNewProjectFromTemplate( const QString & templ ) { - loadProject( _template ); + loadProject( templ ); // clear file-name so that user doesn't overwrite template when // saving... m_fileName = m_oldFileName = ""; @@ -909,7 +928,7 @@ void Song::createNewProjectFromTemplate( const QString & _template ) // load given song -void Song::loadProject( const QString & _file_name ) +void Song::loadProject( const QString & fileName ) { QDomNode node; @@ -917,13 +936,13 @@ void Song::loadProject( const QString & _file_name ) Engine::projectJournal()->setJournalling( false ); - m_fileName = _file_name; - m_oldFileName = _file_name; + m_fileName = fileName; + m_oldFileName = fileName; DataFile dataFile( m_fileName ); // if file could not be opened, head-node is null and we create // new project - if( dataFile.head().isNull() ) + if( dataFile.validate( fileName.right( fileName.lastIndexOf(".") ) ) ) { return; } @@ -1023,7 +1042,7 @@ void Song::loadProject( const QString & _file_name ) Engine::mixer()->unlock(); - ConfigManager::inst()->addRecentlyOpenedProject( _file_name ); + ConfigManager::inst()->addRecentlyOpenedProject( fileName ); Engine::projectJournal()->setJournalling( true ); @@ -1053,7 +1072,7 @@ void Song::loadProject( const QString & _file_name ) // only save current song as _filename and do nothing else -bool Song::saveProjectFile( const QString & _filename ) +bool Song::saveProjectFile( const QString & filename ) { DataFile::LocaleHelper localeHelper( DataFile::LocaleHelper::ModeSave ); @@ -1079,7 +1098,7 @@ bool Song::saveProjectFile( const QString & _filename ) saveControllerStates( dataFile, dataFile.content() ); - return dataFile.writeFile( _filename ); + return dataFile.writeFile( filename ); } @@ -1157,23 +1176,23 @@ void Song::importProject() -void Song::saveControllerStates( QDomDocument & _doc, QDomElement & _this ) +void Song::saveControllerStates( QDomDocument & doc, QDomElement & element ) { // save settings of controllers - QDomElement controllersNode =_doc.createElement( "controllers" ); - _this.appendChild( controllersNode ); + QDomElement controllersNode = doc.createElement( "controllers" ); + element.appendChild( controllersNode ); for( int i = 0; i < m_controllers.size(); ++i ) { - m_controllers[i]->saveState( _doc, controllersNode ); + m_controllers[i]->saveState( doc, controllersNode ); } } -void Song::restoreControllerStates( const QDomElement & _this ) +void Song::restoreControllerStates( const QDomElement & element ) { - QDomNode node = _this.firstChild(); + QDomNode node = element.firstChild(); while( !node.isNull() ) { Controller * c = Controller::create( node.toElement(), this ); @@ -1194,10 +1213,10 @@ void Song::restoreControllerStates( const QDomElement & _this ) void Song::exportProjectTracks() { - exportProject(true); + exportProject( true ); } -void Song::exportProject(bool multiExport) +void Song::exportProject( bool multiExport ) { if( isEmpty() ) { @@ -1210,7 +1229,8 @@ void Song::exportProject(bool multiExport) } FileDialog efd( gui->mainWindow() ); - if (multiExport) + + if ( multiExport ) { efd.setFileMode( FileDialog::Directory); efd.setWindowTitle( tr( "Select directory for writing exported tracks..." ) ); @@ -1230,18 +1250,18 @@ void Song::exportProject(bool multiExport) ++idx; } efd.setNameFilters( types ); - QString base_filename; + QString baseFilename; if( !m_fileName.isEmpty() ) { efd.setDirectory( QFileInfo( m_fileName ).absolutePath() ); - base_filename = QFileInfo( m_fileName ).completeBaseName(); + baseFilename = QFileInfo( m_fileName ).completeBaseName(); } else { efd.setDirectory( ConfigManager::inst()->userProjectsDir() ); - base_filename = tr( "untitled" ); + baseFilename = tr( "untitled" ); } - efd.selectFile( base_filename + __fileEncodeDevices[0].m_extension ); + efd.selectFile( baseFilename + __fileEncodeDevices[0].m_extension ); efd.setWindowTitle( tr( "Select file for project-export..." ) ); } @@ -1268,13 +1288,71 @@ void Song::exportProject(bool multiExport) } } - const QString export_file_name = efd.selectedFiles()[0] + suffix; - ExportProjectDialog epd( export_file_name, gui->mainWindow(), multiExport ); + const QString exportFileName = efd.selectedFiles()[0] + suffix; + ExportProjectDialog epd( exportFileName, gui->mainWindow(), multiExport ); epd.exec(); } } +void Song::exportProjectMidi() +{ + if( isEmpty() ) + { + QMessageBox::information( gui->mainWindow(), + tr( "Empty project" ), + tr( "This project is empty so exporting makes " + "no sense. Please put some items into " + "Song Editor first!" ) ); + return; + } + + FileDialog efd( gui->mainWindow() ); + + efd.setFileMode( FileDialog::AnyFile ); + + QStringList types; + types << tr("MIDI File (*.mid)"); + efd.setNameFilters( types ); + QString base_filename; + if( !m_fileName.isEmpty() ) + { + efd.setDirectory( QFileInfo( m_fileName ).absolutePath() ); + base_filename = QFileInfo( m_fileName ).completeBaseName(); + } + else + { + efd.setDirectory( ConfigManager::inst()->userProjectsDir() ); + base_filename = tr( "untitled" ); + } + efd.selectFile( base_filename + ".mid" ); + efd.setWindowTitle( tr( "Select file for project-export..." ) ); + + efd.setAcceptMode( FileDialog::AcceptSave ); + + + if( efd.exec() == QDialog::Accepted && !efd.selectedFiles().isEmpty() && !efd.selectedFiles()[0].isEmpty() ) + { + const QString suffix = ".mid"; + + QString export_filename = efd.selectedFiles()[0]; + if (!export_filename.endsWith(suffix)) export_filename += suffix; + + // NOTE start midi export + + // instantiate midi export plugin + TrackContainer::TrackList tracks; + tracks += Engine::getSong()->tracks(); + tracks += Engine::getBBTrackContainer()->tracks(); + ExportFilter *exf = dynamic_cast (Plugin::instantiate("midiexport", NULL, NULL)); + if (exf==NULL) { + qDebug() << "failed to load midi export filter!"; + return; + } + exf->tryExport(tracks, Engine::getSong()->getTempo(), export_filename); + } +} + void Song::updateFramesPerTick() @@ -1301,11 +1379,11 @@ void Song::setModified() -void Song::addController( Controller * _c ) +void Song::addController( Controller * c ) { - if( _c != NULL && !m_controllers.contains( _c ) ) + if( c != NULL && m_controllers.contains( c ) == false ) { - m_controllers.append( _c ); + m_controllers.append( c ); emit dataChanged(); } } @@ -1313,9 +1391,9 @@ void Song::addController( Controller * _c ) -void Song::removeController( Controller * _controller ) +void Song::removeController( Controller * controller ) { - int index = m_controllers.indexOf( _controller ); + int index = m_controllers.indexOf( controller ); if( index != -1 ) { m_controllers.remove( index ); @@ -1330,6 +1408,7 @@ void Song::removeController( Controller * _controller ) + void Song::clearErrors() { m_errors->clear(); @@ -1365,3 +1444,7 @@ QString* Song::errorSummary() return errors; } + + + + diff --git a/src/core/Track.cpp b/src/core/Track.cpp index f551a172a..4f5440af0 100644 --- a/src/core/Track.cpp +++ b/src/core/Track.cpp @@ -102,9 +102,9 @@ TextFloat * TrackContentObjectView::s_textFloat = NULL; * * \param _track The track that will contain the new object */ -TrackContentObject::TrackContentObject( Track * _track ) : - Model( _track ), - m_track( _track ), +TrackContentObject::TrackContentObject( Track * track ) : + Model( track ), + m_track( track ), m_name( QString::null ), m_startPosition(), m_length(), @@ -149,11 +149,11 @@ TrackContentObject::~TrackContentObject() * * \param _pos The new position of the track content object. */ -void TrackContentObject::movePosition( const MidiTime & _pos ) +void TrackContentObject::movePosition( const MidiTime & pos ) { - if( m_startPosition != _pos ) + if( m_startPosition != pos ) { - m_startPosition = _pos; + m_startPosition = pos; Engine::getSong()->updateLength(); } emit positionChanged(); @@ -169,11 +169,11 @@ void TrackContentObject::movePosition( const MidiTime & _pos ) * * \param _length The new length of the track content object. */ -void TrackContentObject::changeLength( const MidiTime & _length ) +void TrackContentObject::changeLength( const MidiTime & length ) { - if( m_length != _length ) + if( m_length != length ) { - m_length = _length; + m_length = length; Engine::getSong()->updateLength(); } emit lengthChanged(); @@ -246,12 +246,12 @@ void TrackContentObject::toggleMute() * \param _tco The track content object to be displayed * \param _tv The track view that will contain the new object */ -TrackContentObjectView::TrackContentObjectView( TrackContentObject * _tco, - TrackView * _tv ) : - selectableObject( _tv->getTrackContentWidget() ), +TrackContentObjectView::TrackContentObjectView( TrackContentObject * tco, + TrackView * tv ) : + selectableObject( tv->getTrackContentWidget() ), ModelView( NULL, this ), - m_tco( _tco ), - m_trackView( _tv ), + m_tco( tco ), + m_trackView( tv ), m_action( NoAction ), m_initialMousePos( QPoint( 0, 0 ) ), m_initialMouseGlobalPos( QPoint( 0, 0 ) ), @@ -272,7 +272,7 @@ TrackContentObjectView::TrackContentObjectView( TrackContentObject * _tco, move( 0, 1 ); show(); - setFixedHeight( _tv->getTrackContentWidget()->height() - 2 ); + setFixedHeight( tv->getTrackContentWidget()->height() - 2 ); setAcceptDrops( true ); setMouseTracking( true ); @@ -332,12 +332,12 @@ QColor TrackContentObjectView::textColor() const { return m_textColor; } //! \brief CSS theming qproperty access method -void TrackContentObjectView::setFgColor( const QColor & _c ) -{ m_fgColor = QColor( _c ); } +void TrackContentObjectView::setFgColor( const QColor & c ) +{ m_fgColor = QColor( c ); } //! \brief CSS theming qproperty access method -void TrackContentObjectView::setTextColor( const QColor & _c ) -{ m_textColor = QColor( _c ); } +void TrackContentObjectView::setTextColor( const QColor & c ) +{ m_textColor = QColor( c ); } /*! \brief Close a trackContentObjectView @@ -438,19 +438,19 @@ void TrackContentObjectView::updatePosition() * We need to notify Qt to change our display if something being * dragged has entered our 'airspace'. * - * \param _dee The QDragEnterEvent to watch. + * \param dee The QDragEnterEvent to watch. */ -void TrackContentObjectView::dragEnterEvent( QDragEnterEvent * _dee ) +void TrackContentObjectView::dragEnterEvent( QDragEnterEvent * dee ) { TrackContentWidget * tcw = getTrackView()->getTrackContentWidget(); MidiTime tcoPos = MidiTime( m_tco->startPosition().getTact(), 0 ); - if( tcw->canPasteSelection( tcoPos, _dee->mimeData() ) == false ) + if( tcw->canPasteSelection( tcoPos, dee->mimeData() ) == false ) { - _dee->ignore(); + dee->ignore(); } else { - StringPairDrag::processDragEnterEvent( _dee, "tco_" + + StringPairDrag::processDragEnterEvent( dee, "tco_" + QString::number( m_tco->getTrack()->type() ) ); } } @@ -465,12 +465,12 @@ void TrackContentObjectView::dragEnterEvent( QDragEnterEvent * _dee ) * to take the xml of the track content object and turn it into something * we can write over our current state. * - * \param _de The QDropEvent to handle. + * \param de The QDropEvent to handle. */ -void TrackContentObjectView::dropEvent( QDropEvent * _de ) +void TrackContentObjectView::dropEvent( QDropEvent * de ) { - QString type = StringPairDrag::decodeKey( _de ); - QString value = StringPairDrag::decodeValue( _de ); + QString type = StringPairDrag::decodeKey( de ); + QString value = StringPairDrag::decodeValue( de ); // Track must be the same type to paste into if( type != ( "tco_" + QString::number( m_tco->getTrack()->type() ) ) ) @@ -483,15 +483,15 @@ void TrackContentObjectView::dropEvent( QDropEvent * _de ) { TrackContentWidget * tcw = getTrackView()->getTrackContentWidget(); MidiTime tcoPos = MidiTime( m_tco->startPosition().getTact(), 0 ); - if( tcw->pasteSelection( tcoPos, _de ) == true ) + if( tcw->pasteSelection( tcoPos, de ) == true ) { - _de->accept(); + de->accept(); } return; } // Don't allow pasting a tco into itself. - QObject* qwSource = _de->source(); + QObject* qwSource = de->source(); if( qwSource != NULL && dynamic_cast( qwSource ) == this ) { @@ -505,7 +505,7 @@ void TrackContentObjectView::dropEvent( QDropEvent * _de ) m_tco->restoreState( tcos.firstChildElement().firstChildElement() ); m_tco->movePosition( pos ); AutomationPattern::resolveAllIDs(); - _de->accept(); + de->accept(); } @@ -513,17 +513,17 @@ void TrackContentObjectView::dropEvent( QDropEvent * _de ) /*! \brief Handle a dragged selection leaving our 'airspace'. * - * \param _e The QEvent to watch. + * \param e The QEvent to watch. */ -void TrackContentObjectView::leaveEvent( QEvent * _e ) +void TrackContentObjectView::leaveEvent( QEvent * e ) { while( QApplication::overrideCursor() != NULL ) { QApplication::restoreOverrideCursor(); } - if( _e != NULL ) + if( e != NULL ) { - QWidget::leaveEvent( _e ); + QWidget::leaveEvent( e ); } } @@ -589,20 +589,20 @@ DataFile TrackContentObjectView::createTCODataFiles( * * or if ctrl-middle button, mute the track content object * * or if middle button, maybe delete the track content object. * - * \param _me The QMouseEvent to handle. + * \param me The QMouseEvent to handle. */ -void TrackContentObjectView::mousePressEvent( QMouseEvent * _me ) +void TrackContentObjectView::mousePressEvent( QMouseEvent * me ) { - setInitialMousePos( _me->pos() ); + setInitialMousePos( me->pos() ); if( m_trackView->trackContainerView()->allowRubberband() == true && - _me->button() == Qt::LeftButton ) + me->button() == Qt::LeftButton ) { if( m_trackView->trackContainerView()->rubberBandActive() == true ) { // Propagate to trackView for rubberbanding - selectableObject::mousePressEvent( _me ); + selectableObject::mousePressEvent( me ); } - else if ( _me->modifiers() & Qt::ControlModifier ) + else if ( me->modifiers() & Qt::ControlModifier ) { if( isSelected() == true ) { @@ -613,7 +613,7 @@ void TrackContentObjectView::mousePressEvent( QMouseEvent * _me ) m_action = ToggleSelected; } } - else if( !_me->modifiers() ) + else if( !me->modifiers() ) { if( isSelected() == true ) { @@ -621,8 +621,8 @@ void TrackContentObjectView::mousePressEvent( QMouseEvent * _me ) } } } - else if( _me->button() == Qt::LeftButton && - _me->modifiers() & Qt::ControlModifier ) + else if( me->button() == Qt::LeftButton && + me->modifiers() & Qt::ControlModifier ) { // start drag-action QVector tcoViews; @@ -636,7 +636,7 @@ void TrackContentObjectView::mousePressEvent( QMouseEvent * _me ) m_tco->getTrack()->type() ), dataFile.toString(), thumbnail, this ); } - else if( _me->button() == Qt::LeftButton && + else if( me->button() == Qt::LeftButton && /* engine::mainWindow()->isShiftPressed() == false &&*/ fixedTCOs() == false ) { @@ -645,9 +645,9 @@ void TrackContentObjectView::mousePressEvent( QMouseEvent * _me ) // move or resize m_tco->setJournalling( false ); - setInitialMousePos( _me->pos() ); + setInitialMousePos( me->pos() ); - if( _me->x() < width() - RESIZE_GRIP_WIDTH ) + if( me->x() < width() - RESIZE_GRIP_WIDTH ) { m_action = Move; m_oldTime = m_tco->startPosition(); @@ -675,23 +675,23 @@ void TrackContentObjectView::mousePressEvent( QMouseEvent * _me ) } // s_textFloat->reparent( this ); // setup text-float as if TCO was already moved/resized - mouseMoveEvent( _me ); + mouseMoveEvent( me ); s_textFloat->show(); } - else if( _me->button() == Qt::RightButton ) + else if( me->button() == Qt::RightButton ) { - if( _me->modifiers() & Qt::ControlModifier ) + if( me->modifiers() & Qt::ControlModifier ) { m_tco->toggleMute(); } - else if( _me->modifiers() & Qt::ShiftModifier && fixedTCOs() == false ) + else if( me->modifiers() & Qt::ShiftModifier && fixedTCOs() == false ) { remove(); } } - else if( _me->button() == Qt::MidButton ) + else if( me->button() == Qt::MidButton ) { - if( _me->modifiers() & Qt::ControlModifier ) + if( me->modifiers() & Qt::ControlModifier ) { m_tco->toggleMute(); } @@ -715,17 +715,17 @@ void TrackContentObjectView::mousePressEvent( QMouseEvent * _me ) * * or if in resize mode, resize ourselves, * * otherwise ??? * - * \param _me The QMouseEvent to handle. + * \param me The QMouseEvent to handle. * \todo what does the final else case do here? */ -void TrackContentObjectView::mouseMoveEvent( QMouseEvent * _me ) +void TrackContentObjectView::mouseMoveEvent( QMouseEvent * me ) { if( m_action == CopySelection ) { - if( mouseMovedDistance( _me, 2 ) == true && + if( mouseMovedDistance( me, 2 ) == true && m_trackView->trackContainerView()->allowRubberband() == true && m_trackView->trackContainerView()->rubberBandActive() == false && - ( _me->modifiers() & Qt::ControlModifier ) ) + ( me->modifiers() & Qt::ControlModifier ) ) { // Clear the action here because mouseReleaseEvent will not get // triggered once we go into drag. @@ -760,7 +760,7 @@ void TrackContentObjectView::mouseMoveEvent( QMouseEvent * _me ) } } - if( _me->modifiers() & Qt::ControlModifier ) + if( me->modifiers() & Qt::ControlModifier ) { delete m_hint; m_hint = NULL; @@ -769,13 +769,13 @@ void TrackContentObjectView::mouseMoveEvent( QMouseEvent * _me ) const float ppt = m_trackView->trackContainerView()->pixelsPerTact(); if( m_action == Move ) { - const int x = mapToParent( _me->pos() ).x() - m_initialMousePos.x(); + 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 ) + if( ! ( me->modifiers() & Qt::ControlModifier ) + && me->button() == Qt::NoButton ) { t = t.toNearestTact(); } @@ -790,7 +790,7 @@ void TrackContentObjectView::mouseMoveEvent( QMouseEvent * _me ) } else if( m_action == MoveSelection ) { - const int dx = _me->x() - m_initialMousePos.x(); + const int dx = me->x() - m_initialMousePos.x(); QVector so = m_trackView->trackContainerView()->selectedObjects(); QVector tcos; @@ -819,8 +819,8 @@ void TrackContentObjectView::mouseMoveEvent( QMouseEvent * _me ) t = ( *it )->startPosition() + static_cast( dx *MidiTime::ticksPerTact() / ppt )-smallest_pos; - if( ! ( _me->modifiers() & Qt::AltModifier ) - && _me->button() == Qt::NoButton ) + if( ! ( me->modifiers() & Qt::AltModifier ) + && me->button() == Qt::NoButton ) { t = t.toNearestTact(); } @@ -829,8 +829,8 @@ void TrackContentObjectView::mouseMoveEvent( QMouseEvent * _me ) } else 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 ) + 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() ); } @@ -850,7 +850,7 @@ void TrackContentObjectView::mouseMoveEvent( QMouseEvent * _me ) } else { - if( _me->x() > width() - RESIZE_GRIP_WIDTH && !_me->buttons() && !m_tco->getAutoResize() ) + if( me->x() > width() - RESIZE_GRIP_WIDTH && !me->buttons() && !m_tco->getAutoResize() ) { if( QApplication::overrideCursor() != NULL && QApplication::overrideCursor()->shape() != @@ -879,16 +879,16 @@ void TrackContentObjectView::mouseMoveEvent( QMouseEvent * _me ) * If we're in move or resize mode, journal the change as appropriate. * Then tidy up. * - * \param _me The QMouseEvent to handle. + * \param me The QMouseEvent to handle. */ -void TrackContentObjectView::mouseReleaseEvent( QMouseEvent * _me ) +void TrackContentObjectView::mouseReleaseEvent( QMouseEvent * me ) { // If the CopySelection was chosen as the action due to mouse movement, // it will have been cleared. At this point Toggle is the desired action. // An active StringPairDrag will prevent this method from being called, // so a real CopySelection would not have occurred. if( m_action == CopySelection || - ( m_action == ToggleSelected && mouseMovedDistance( _me, 2 ) == false ) ) + ( m_action == ToggleSelected && mouseMovedDistance( me, 2 ) == false ) ) { setSelected( !isSelected() ); } @@ -902,7 +902,7 @@ void TrackContentObjectView::mouseReleaseEvent( QMouseEvent * _me ) m_hint = NULL; s_textFloat->hide(); leaveEvent( NULL ); - selectableObject::mouseReleaseEvent( _me ); + selectableObject::mouseReleaseEvent( me ); } @@ -913,11 +913,11 @@ void TrackContentObjectView::mouseReleaseEvent( QMouseEvent * _me ) * Set up the various context menu events that can apply to a * track content object view. * - * \param _cme The QContextMenuEvent to add the actions to. + * \param cme The QContextMenuEvent to add the actions to. */ -void TrackContentObjectView::contextMenuEvent( QContextMenuEvent * _cme ) +void TrackContentObjectView::contextMenuEvent( QContextMenuEvent * cme ) { - if( _cme->modifiers() ) + if( cme->modifiers() ) { return; } @@ -966,9 +966,9 @@ float TrackContentObjectView::pixelsPerTact() * \param _me The QMouseEvent. * \param distance The threshold distance that the mouse has moved to return true. */ -bool TrackContentObjectView::mouseMovedDistance( QMouseEvent * _me, int distance ) +bool TrackContentObjectView::mouseMovedDistance( QMouseEvent * me, int distance ) { - QPoint dPos = mapToGlobal( _me->pos() ) - m_initialMouseGlobalPos; + QPoint dPos = mapToGlobal( me->pos() ) - m_initialMouseGlobalPos; const int pixelsMoved = dPos.manhattanLength(); return ( pixelsMoved > distance || pixelsMoved < -distance ); } @@ -985,17 +985,17 @@ bool TrackContentObjectView::mouseMovedDistance( QMouseEvent * _me, int distance * The content widget comprises the 'grip bar' and the 'tools' button * for the track's context menu. * - * \param _track The parent track. + * \param parent The parent track. */ -TrackContentWidget::TrackContentWidget( TrackView * _parent ) : - QWidget( _parent ), - m_trackView( _parent ), +TrackContentWidget::TrackContentWidget( TrackView * parent ) : + QWidget( parent ), + m_trackView( parent ), m_darkerColor( Qt::SolidPattern ), m_lighterColor( Qt::SolidPattern ) { setAcceptDrops( true ); - connect( _parent->trackContainerView(), + connect( parent->trackContainerView(), SIGNAL( positionChanged( const MidiTime & ) ), this, SLOT( changePosition( const MidiTime & ) ) ); @@ -1065,13 +1065,13 @@ void TrackContentWidget::updateBackground() * Adds a(nother) trackContentObjectView to our list of views. We also * check that our position is up-to-date. * - * \param _tcov The trackContentObjectView to add. + * \param tcov The trackContentObjectView to add. */ -void TrackContentWidget::addTCOView( TrackContentObjectView * _tcov ) +void TrackContentWidget::addTCOView( TrackContentObjectView * tcov ) { - TrackContentObject * tco = _tcov->getTrackContentObject(); + TrackContentObject * tco = tcov->getTrackContentObject(); - m_tcoViews.push_back( _tcov ); + m_tcoViews.push_back( tcov ); tco->saveJournallingState( false ); changePosition(); @@ -1085,13 +1085,13 @@ void TrackContentWidget::addTCOView( TrackContentObjectView * _tcov ) * * Removes the given trackContentObjectView from our list of views. * - * \param _tcov The trackContentObjectView to add. + * \param tcov The trackContentObjectView to add. */ -void TrackContentWidget::removeTCOView( TrackContentObjectView * _tcov ) +void TrackContentWidget::removeTCOView( TrackContentObjectView * tcov ) { tcoViewVector::iterator it = qFind( m_tcoViews.begin(), m_tcoViews.end(), - _tcov ); + tcov ); if( it != m_tcoViews.end() ) { m_tcoViews.erase( it ); @@ -1123,13 +1123,13 @@ void TrackContentWidget::update() // change of visible viewport /*! \brief Move the trackContentWidget to a new place in time * - * \param _new_pos The MIDI time to move to. + * \param newPos The MIDI time to move to. */ -void TrackContentWidget::changePosition( const MidiTime & _new_pos ) +void TrackContentWidget::changePosition( const MidiTime & newPos ) { if( m_trackView->trackContainerView() == gui->getBBEditor()->trackContainerView() ) { - const int cur_bb = Engine::getBBTrackContainer()->currentBB(); + const int curBB = Engine::getBBTrackContainer()->currentBB(); setUpdatesEnabled( false ); // first show TCO for current BB... @@ -1137,7 +1137,7 @@ void TrackContentWidget::changePosition( const MidiTime & _new_pos ) it != m_tcoViews.end(); ++it ) { if( ( *it )->getTrackContentObject()-> - startPosition().getTact() == cur_bb ) + startPosition().getTact() == curBB ) { ( *it )->move( 0, ( *it )->y() ); ( *it )->raise(); @@ -1153,7 +1153,7 @@ void TrackContentWidget::changePosition( const MidiTime & _new_pos ) it != m_tcoViews.end(); ++it ) { if( ( *it )->getTrackContentObject()-> - startPosition().getTact() != cur_bb ) + startPosition().getTact() != curBB ) { ( *it )->hide(); } @@ -1162,7 +1162,7 @@ void TrackContentWidget::changePosition( const MidiTime & _new_pos ) return; } - MidiTime pos = _new_pos; + MidiTime pos = newPos; if( pos < 0 ) { pos = m_trackView->trackContainerView()->currentPosition(); @@ -1211,13 +1211,13 @@ void TrackContentWidget::changePosition( const MidiTime & _new_pos ) /*! \brief Return the position of the trackContentWidget in Tacts. * - * \param _mouse_x the mouse's current X position in pixels. + * \param mouseX the mouse's current X position in pixels. */ -MidiTime TrackContentWidget::getPosition( int _mouse_x ) +MidiTime TrackContentWidget::getPosition( int mouseX ) { TrackContainerView * tv = m_trackView->trackContainerView(); return MidiTime( tv->currentPosition() + - _mouse_x * + mouseX * MidiTime::ticksPerTact() / static_cast( tv->pixelsPerTact() ) ); } @@ -1227,18 +1227,18 @@ MidiTime TrackContentWidget::getPosition( int _mouse_x ) /*! \brief Respond to a drag enter event on the trackContentWidget * - * \param _dee the Drag Enter Event to respond to + * \param dee the Drag Enter Event to respond to */ -void TrackContentWidget::dragEnterEvent( QDragEnterEvent * _dee ) +void TrackContentWidget::dragEnterEvent( QDragEnterEvent * dee ) { - MidiTime tcoPos = MidiTime( getPosition( _dee->pos().x() ).getTact(), 0 ); - if( canPasteSelection( tcoPos, _dee->mimeData() ) == false ) + MidiTime tcoPos = MidiTime( getPosition( dee->pos().x() ).getTact(), 0 ); + if( canPasteSelection( tcoPos, dee->mimeData() ) == false ) { - _dee->ignore(); + dee->ignore(); } else { - StringPairDrag::processDragEnterEvent( _dee, "tco_" + + StringPairDrag::processDragEnterEvent( dee, "tco_" + QString::number( getTrack()->type() ) ); } } @@ -1249,7 +1249,7 @@ void TrackContentWidget::dragEnterEvent( QDragEnterEvent * _dee ) /*! \brief Returns whether a selection of TCOs can be pasted into this * * \param tcoPos the position of the TCO slot being pasted on - * \param _de the DropEvent generated + * \param de the DropEvent generated */ bool TrackContentWidget::canPasteSelection( MidiTime tcoPos, const QMimeData * mimeData ) { @@ -1292,7 +1292,7 @@ bool TrackContentWidget::canPasteSelection( MidiTime tcoPos, const QMimeData * m QDomNodeList tcoNodes = tcoParent.childNodes(); // Determine if all the TCOs will land on a valid track - for( int i = 0; imimeData() ) == false ) + if( canPasteSelection( tcoPos, de->mimeData() ) == false ) { return false; } - QString type = StringPairDrag::decodeKey( _de ); - QString value = StringPairDrag::decodeValue( _de ); + QString type = StringPairDrag::decodeKey( de ); + QString value = StringPairDrag::decodeValue( de ); getTrack()->addJournalCheckPoint(); @@ -1408,14 +1408,14 @@ bool TrackContentWidget::pasteSelection( MidiTime tcoPos, QDropEvent * _de ) /*! \brief Respond to a drop event on the trackContentWidget * - * \param _de the Drop Event to respond to + * \param de the Drop Event to respond to */ -void TrackContentWidget::dropEvent( QDropEvent * _de ) +void TrackContentWidget::dropEvent( QDropEvent * de ) { - MidiTime tcoPos = MidiTime( getPosition( _de->pos().x() ).getTact(), 0 ); - if( pasteSelection( tcoPos, _de ) == true ) + MidiTime tcoPos = MidiTime( getPosition( de->pos().x() ).getTact(), 0 ); + if( pasteSelection( tcoPos, de ) == true ) { - _de->accept(); + de->accept(); } } @@ -1424,29 +1424,29 @@ void TrackContentWidget::dropEvent( QDropEvent * _de ) /*! \brief Respond to a mouse press on the trackContentWidget * - * \param _me the mouse press event to respond to + * \param me the mouse press event to respond to */ -void TrackContentWidget::mousePressEvent( QMouseEvent * _me ) +void TrackContentWidget::mousePressEvent( QMouseEvent * me ) { if( m_trackView->trackContainerView()->allowRubberband() == true ) { - QWidget::mousePressEvent( _me ); + QWidget::mousePressEvent( me ); } - else if( _me->modifiers() & Qt::ShiftModifier ) + else if( me->modifiers() & Qt::ShiftModifier ) { - QWidget::mousePressEvent( _me ); + QWidget::mousePressEvent( me ); } - else if( _me->button() == Qt::LeftButton && + else if( me->button() == Qt::LeftButton && !m_trackView->trackContainerView()->fixedTCOs() ) { - const MidiTime pos = getPosition( _me->x() ).getTact() * + getTrack()->addJournalCheckPoint(); + const MidiTime pos = getPosition( me->x() ).getTact() * MidiTime::ticksPerTact(); TrackContentObject * tco = getTrack()->createTCO( pos ); tco->saveJournallingState( false ); tco->movePosition( pos ); tco->restoreJournallingState(); - } } @@ -1455,9 +1455,9 @@ void TrackContentWidget::mousePressEvent( QMouseEvent * _me ) /*! \brief Repaint the trackContentWidget on command * - * \param _pe the Paint Event to respond to + * \param pe the Paint Event to respond to */ -void TrackContentWidget::paintEvent( QPaintEvent * _pe ) +void TrackContentWidget::paintEvent( QPaintEvent * pe ) { // Assume even-pixels-per-tact. Makes sense, should be like this anyways const TrackContainerView * tcv = m_trackView->trackContainerView(); @@ -1502,13 +1502,13 @@ Track * TrackContentWidget::getTrack() /*! \brief Return the end position of the trackContentWidget in Tacts. * - * \param _pos_start the starting position of the Widget (from getPosition()) + * \param posStart the starting position of the Widget (from getPosition()) */ -MidiTime TrackContentWidget::endPosition( const MidiTime & _pos_start ) +MidiTime TrackContentWidget::endPosition( const MidiTime & posStart ) { const float ppt = m_trackView->trackContainerView()->pixelsPerTact(); const int w = width(); - return _pos_start + static_cast( w * MidiTime::ticksPerTact() / ppt ); + return posStart + static_cast( w * MidiTime::ticksPerTact() / ppt ); } @@ -1545,11 +1545,11 @@ QPixmap * TrackOperationsWidget::s_grip = NULL; /*!< grip pixmap */ * * The trackOperationsWidget is the grip and the mute button of a track. * - * \param _parent the trackView to contain this widget + * \param parent the trackView to contain this widget */ -TrackOperationsWidget::TrackOperationsWidget( TrackView * _parent ) : - QWidget( _parent ), /*!< The parent widget */ - m_trackView( _parent ) /*!< The parent track view */ +TrackOperationsWidget::TrackOperationsWidget( TrackView * parent ) : + QWidget( parent ), /*!< The parent widget */ + m_trackView( parent ) /*!< The parent track view */ { if( s_grip == NULL ) { @@ -1560,9 +1560,9 @@ TrackOperationsWidget::TrackOperationsWidget( TrackView * _parent ) : ToolTip::add( this, tr( "Press while clicking on move-grip " "to begin a new drag'n'drop-action." ) ); - QMenu * to_menu = new QMenu( this ); - to_menu->setFont( pointSize<9>( to_menu->font() ) ); - connect( to_menu, SIGNAL( aboutToShow() ), this, SLOT( updateMenu() ) ); + QMenu * toMenu = new QMenu( this ); + toMenu->setFont( pointSize<9>( toMenu->font() ) ); + connect( toMenu, SIGNAL( aboutToShow() ), this, SLOT( updateMenu() ) ); setObjectName( "automationEnabled" ); @@ -1571,7 +1571,7 @@ TrackOperationsWidget::TrackOperationsWidget( TrackView * _parent ) : m_trackOps = new QPushButton( this ); m_trackOps->move( 12, 1 ); m_trackOps->setFocusPolicy( Qt::NoFocus ); - m_trackOps->setMenu( to_menu ); + m_trackOps->setMenu( toMenu ); ToolTip::add( m_trackOps, tr( "Actions for this track" ) ); @@ -1630,12 +1630,12 @@ TrackOperationsWidget::~TrackOperationsWidget() * * Otherwise, ignore all other events. * - * \param _me The mouse event to respond to. + * \param me The mouse event to respond to. */ -void TrackOperationsWidget::mousePressEvent( QMouseEvent * _me ) +void TrackOperationsWidget::mousePressEvent( QMouseEvent * me ) { - if( _me->button() == Qt::LeftButton && - _me->modifiers() & Qt::ControlModifier && + if( me->button() == Qt::LeftButton && + me->modifiers() & Qt::ControlModifier && m_trackView->getTrack()->type() != Track::BBTrack ) { DataFile dataFile( DataFile::DragNDropData ); @@ -1646,17 +1646,16 @@ void TrackOperationsWidget::mousePressEvent( QMouseEvent * _me ) m_trackView->getTrackSettingsWidget() ), this ); } - else if( _me->button() == Qt::LeftButton ) + else if( me->button() == Qt::LeftButton ) { // track-widget (parent-widget) initiates track-move - _me->ignore(); + me->ignore(); } } - /*! \brief Repaint the trackOperationsWidget * * If we're not moving, and in the Beat+Bassline Editor, then turn @@ -1666,9 +1665,9 @@ void TrackOperationsWidget::mousePressEvent( QMouseEvent * _me ) * Otherwise, hide ourselves. * * \todo Flesh this out a bit - is it correct? - * \param _pe The paint event to respond to + * \param pe The paint event to respond to */ -void TrackOperationsWidget::paintEvent( QPaintEvent * _pe ) +void TrackOperationsWidget::paintEvent( QPaintEvent * pe ) { QPainter p( this ); p.fillRect( rect(), palette().brush(QPalette::Background) ); @@ -1710,29 +1709,6 @@ void TrackOperationsWidget::clearTrack() -/*! \brief Create and assign a new FX Channel for this track */ -void TrackOperationsWidget::createFxLine() -{ - int channelIndex = gui->fxMixerView()->addNewChannel(); - - Engine::fxMixer()->effectChannel( channelIndex )->m_name = m_trackView->getTrack()->name(); - - assignFxLine(channelIndex); -} - - - -/*! \brief Assign a specific FX Channel for this track */ -void TrackOperationsWidget::assignFxLine(int channelIndex) -{ - Track * track = m_trackView->getTrack(); - dynamic_cast( track )->effectChannelModel()->setValue( channelIndex ); - - gui->fxMixerView()->setCurrentFxLine( channelIndex ); -} - - - /*! \brief Remove this track from the track list * */ @@ -1754,54 +1730,31 @@ void TrackOperationsWidget::removeTrack() */ void TrackOperationsWidget::updateMenu() { - QMenu * to_menu = m_trackOps->menu(); - to_menu->clear(); - to_menu->addAction( embed::getIconPixmap( "edit_copy", 16, 16 ), + QMenu * toMenu = m_trackOps->menu(); + toMenu->clear(); + toMenu->addAction( embed::getIconPixmap( "edit_copy", 16, 16 ), tr( "Clone this track" ), this, SLOT( cloneTrack() ) ); - to_menu->addAction( embed::getIconPixmap( "cancel", 16, 16 ), + toMenu->addAction( embed::getIconPixmap( "cancel", 16, 16 ), tr( "Remove this track" ), this, SLOT( removeTrack() ) ); if( ! m_trackView->trackContainerView()->fixedTCOs() ) { - to_menu->addAction( tr( "Clear this track" ), this, SLOT( clearTrack() ) ); + toMenu->addAction( tr( "Clear this track" ), this, SLOT( clearTrack() ) ); } if( InstrumentTrackView * trackView = dynamic_cast( m_trackView ) ) { - int channelIndex = trackView->model()->effectChannelModel()->value(); + QMenu *fxMenu = trackView->createFxMenu( tr( "FX %1: %2" ), tr( "Assign to new FX Channel" )); + toMenu->addMenu(fxMenu); - FxChannel * fxChannel = Engine::fxMixer()->effectChannel( channelIndex ); - - QMenu * fxMenu = new QMenu( tr( "FX %1: %2" ).arg( channelIndex ).arg( fxChannel->m_name ), to_menu ); - QSignalMapper * fxMenuSignalMapper = new QSignalMapper(this); - - fxMenu->addAction("Assign to new FX Channel" , this, SLOT( createFxLine() ) ); - fxMenu->addSeparator(); - - - for (int i = 0; i < Engine::fxMixer()->fxChannels().size(); ++i) - { - FxChannel * currentChannel = Engine::fxMixer()->fxChannels()[i]; - - if ( currentChannel != fxChannel ) - { - 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); - } - } - - to_menu->addMenu(fxMenu); - connect(fxMenuSignalMapper, SIGNAL(mapped(int)), this, SLOT(assignFxLine(int))); - - to_menu->addSeparator(); - to_menu->addMenu( trackView->midiMenu() ); + toMenu->addSeparator(); + toMenu->addMenu( trackView->midiMenu() ); } if( dynamic_cast( m_trackView ) ) { - to_menu->addAction( tr( "Turn all recording on" ), this, SLOT( recordingOn() ) ); - to_menu->addAction( tr( "Turn all recording off" ), this, SLOT( recordingOff() ) ); + toMenu->addAction( tr( "Turn all recording on" ), this, SLOT( recordingOn() ) ); + toMenu->addAction( tr( "Turn all recording off" ), this, SLOT( recordingOff() ) ); } } @@ -1847,15 +1800,15 @@ void TrackOperationsWidget::recordingOff() * The track object is the whole track, linking its contents, its * automation, name, type, and so forth. * - * \param _type The type of track (Song Editor or Beat+Bassline Editor) - * \param _tc The track Container object to encapsulate in this track. + * \param type The type of track (Song Editor or Beat+Bassline Editor) + * \param tc The track Container object to encapsulate in this track. * * \todo check the definitions of all the properties - are they OK? */ -Track::Track( TrackTypes _type, TrackContainer * _tc ) : - Model( _tc ), /*!< The track Model */ - m_trackContainer( _tc ), /*!< The track container object */ - m_type( _type ), /*!< The track type */ +Track::Track( TrackTypes type, TrackContainer * tc ) : + Model( tc ), /*!< The track Model */ + m_trackContainer( tc ), /*!< The track container object */ + m_type( type ), /*!< The track type */ m_name(), /*!< The track's name */ m_mutedModel( false, this, tr( "Muted" ) ), /*!< For controlling track muting */ @@ -1900,27 +1853,27 @@ Track::~Track() /*! \brief Create a track based on the given track type and container. * - * \param _tt The type of track to create - * \param _tc The track container to attach to + * \param tt The type of track to create + * \param tc The track container to attach to */ -Track * Track::create( TrackTypes _tt, TrackContainer * _tc ) +Track * Track::create( TrackTypes tt, TrackContainer * tc ) { Track * t = NULL; - switch( _tt ) + switch( tt ) { - case InstrumentTrack: t = new ::InstrumentTrack( _tc ); break; - case BBTrack: t = new ::BBTrack( _tc ); break; - case SampleTrack: t = new ::SampleTrack( _tc ); break; + case InstrumentTrack: t = new ::InstrumentTrack( tc ); break; + case BBTrack: t = new ::BBTrack( tc ); break; + case SampleTrack: t = new ::SampleTrack( tc ); break; // case EVENT_TRACK: // case VIDEO_TRACK: - case AutomationTrack: t = new ::AutomationTrack( _tc ); break; + case AutomationTrack: t = new ::AutomationTrack( tc ); break; case HiddenAutomationTrack: - t = new ::AutomationTrack( _tc, true ); break; + t = new ::AutomationTrack( tc, true ); break; default: break; } - _tc->updateAfterTrackAdd(); + tc->updateAfterTrackAdd(); return t; } @@ -1930,17 +1883,17 @@ Track * Track::create( TrackTypes _tt, TrackContainer * _tc ) /*! \brief Create a track inside TrackContainer from track type in a QDomElement and restore state from XML * - * \param _this The QDomElement containing the type of track to create - * \param _tc The track container to attach to + * \param element The QDomElement containing the type of track to create + * \param tc The track container to attach to */ -Track * Track::create( const QDomElement & _this, TrackContainer * _tc ) +Track * Track::create( const QDomElement & element, TrackContainer * tc ) { Track * t = create( - static_cast( _this.attribute( "type" ).toInt() ), - _tc ); + static_cast( element.attribute( "type" ).toInt() ), + tc ); if( t != NULL ) { - t->restoreState( _this ); + t->restoreState( element ); } return t; } @@ -1970,31 +1923,31 @@ void Track::clone() * specific settings. Then we iterate through the trackContentObjects * and save all their states in turn. * - * \param _doc The QDomDocument to use to save - * \param _this The The QDomElement to save into + * \param doc The QDomDocument to use to save + * \param element The The QDomElement to save into * \todo Does this accurately describe the parameters? I think not!? * \todo Save the track height */ -void Track::saveSettings( QDomDocument & _doc, QDomElement & _this ) +void Track::saveSettings( QDomDocument & doc, QDomElement & element ) { if( !m_simpleSerializingMode ) { - _this.setTagName( "track" ); + element.setTagName( "track" ); } - _this.setAttribute( "type", type() ); - _this.setAttribute( "name", name() ); - _this.setAttribute( "muted", isMuted() ); - _this.setAttribute( "solo", isSolo() ); + element.setAttribute( "type", type() ); + element.setAttribute( "name", name() ); + element.setAttribute( "muted", isMuted() ); + element.setAttribute( "solo", isSolo() ); if( m_height >= MINIMAL_TRACK_HEIGHT ) { - _this.setAttribute( "height", m_height ); + element.setAttribute( "height", m_height ); } - QDomElement ts_de = _doc.createElement( nodeName() ); + QDomElement tsDe = doc.createElement( nodeName() ); // let actual track (InstrumentTrack, bbTrack, sampleTrack etc.) save // its settings - _this.appendChild( ts_de ); - saveTrackSpecificSettings( _doc, ts_de ); + element.appendChild( tsDe ); + saveTrackSpecificSettings( doc, tsDe ); if( m_simpleSerializingMode ) { @@ -2006,7 +1959,7 @@ void Track::saveSettings( QDomDocument & _doc, QDomElement & _this ) for( tcoVector::const_iterator it = m_trackContentObjects.begin(); it != m_trackContentObjects.end(); ++it ) { - ( *it )->saveState( _doc, _this ); + ( *it )->saveState( doc, element ); } } @@ -2022,26 +1975,26 @@ void Track::saveSettings( QDomDocument & _doc, QDomElement & _this ) * track-specific settings and trackContentObjects states from it * one at a time. * - * \param _this the QDomElement to load track settings from + * \param element the QDomElement to load track settings from * \todo Load the track height. */ -void Track::loadSettings( const QDomElement & _this ) +void Track::loadSettings( const QDomElement & element ) { - if( _this.attribute( "type" ).toInt() != type() ) + if( element.attribute( "type" ).toInt() != type() ) { qWarning( "Current track-type does not match track-type of " "settings-node!\n" ); } - setName( _this.hasAttribute( "name" ) ? _this.attribute( "name" ) : - _this.firstChild().toElement().attribute( "name" ) ); + setName( element.hasAttribute( "name" ) ? element.attribute( "name" ) : + element.firstChild().toElement().attribute( "name" ) ); - setMuted( _this.attribute( "muted" ).toInt() ); - setSolo( _this.attribute( "solo" ).toInt() ); + setMuted( element.attribute( "muted" ).toInt() ); + setSolo( element.attribute( "solo" ).toInt() ); if( m_simpleSerializingMode ) { - QDomNode node = _this.firstChild(); + QDomNode node = element.firstChild(); while( !node.isNull() ) { if( node.isElement() && node.nodeName() == nodeName() ) @@ -2061,7 +2014,7 @@ void Track::loadSettings( const QDomElement & _this ) // m_trackContentObjects.erase( m_trackContentObjects.begin() ); } - QDomNode node = _this.firstChild(); + QDomNode node = element.firstChild(); while( !node.isNull() ) { if( node.isElement() ) @@ -2083,10 +2036,10 @@ void Track::loadSettings( const QDomElement & _this ) node = node.nextSibling(); } - if( _this.attribute( "height" ).toInt() >= MINIMAL_TRACK_HEIGHT && - _this.attribute( "height" ).toInt() <= DEFAULT_TRACK_HEIGHT ) // workaround for #3585927, tobydox/2012-11-11 + if( element.attribute( "height" ).toInt() >= MINIMAL_TRACK_HEIGHT && + element.attribute( "height" ).toInt() <= DEFAULT_TRACK_HEIGHT ) // workaround for #3585927, tobydox/2012-11-11 { - m_height = _this.attribute( "height" ).toInt(); + m_height = element.attribute( "height" ).toInt(); } } @@ -2095,15 +2048,15 @@ void Track::loadSettings( const QDomElement & _this ) /*! \brief Add another TrackContentObject into this track * - * \param _tco The TrackContentObject to attach to this track. + * \param tco The TrackContentObject to attach to this track. */ -TrackContentObject * Track::addTCO( TrackContentObject * _tco ) +TrackContentObject * Track::addTCO( TrackContentObject * tco ) { - m_trackContentObjects.push_back( _tco ); + m_trackContentObjects.push_back( tco ); - emit trackContentObjectAdded( _tco ); + emit trackContentObjectAdded( tco ); - return _tco; // just for convenience + return tco; // just for convenience } @@ -2111,13 +2064,13 @@ TrackContentObject * Track::addTCO( TrackContentObject * _tco ) /*! \brief Remove a given TrackContentObject from this track * - * \param _tco The TrackContentObject to remove from this track. + * \param tco The TrackContentObject to remove from this track. */ -void Track::removeTCO( TrackContentObject * _tco ) +void Track::removeTCO( TrackContentObject * tco ) { tcoVector::iterator it = qFind( m_trackContentObjects.begin(), m_trackContentObjects.end(), - _tco ); + tco ); if( it != m_trackContentObjects.end() ) { m_trackContentObjects.erase( it ); @@ -2158,21 +2111,21 @@ int Track::numOfTCOs() * numbered object from the array. Otherwise we warn the user that * we've somehow requested a TCO that is too large, and create a new * TCO for them. - * \param _tco_number The number of the TrackContentObject to fetch. + * \param tcoNum The number of the TrackContentObject to fetch. * \return the given TrackContentObject or a new one if out of range. * \todo reject TCO numbers less than zero. * \todo if we create a TCO here, should we somehow attach it to the * track? */ -TrackContentObject * Track::getTCO( int _tco_num ) +TrackContentObject * Track::getTCO( int tcoNum ) { - if( _tco_num < m_trackContentObjects.size() ) + if( tcoNum < m_trackContentObjects.size() ) { - return m_trackContentObjects[_tco_num]; + return m_trackContentObjects[tcoNum]; } printf( "called Track::getTCO( %d ), " - "but TCO %d doesn't exist\n", _tco_num, _tco_num ); - return createTCO( _tco_num * MidiTime::ticksPerTact() ); + "but TCO %d doesn't exist\n", tcoNum, tcoNum ); + return createTCO( tcoNum * MidiTime::ticksPerTact() ); } @@ -2181,15 +2134,15 @@ TrackContentObject * Track::getTCO( int _tco_num ) /*! \brief Determine the given TrackContentObject's number in our array. * - * \param _tco The TrackContentObject to search for. + * \param tco The TrackContentObject to search for. * \return its number in our array. */ -int Track::getTCONum( const TrackContentObject * _tco ) +int Track::getTCONum( const TrackContentObject * tco ) { // for( int i = 0; i < getTrackContentWidget()->numOfTCOs(); ++i ) tcoVector::iterator it = qFind( m_trackContentObjects.begin(), m_trackContentObjects.end(), - _tco ); + tco ); if( it != m_trackContentObjects.end() ) { /* if( getTCO( i ) == _tco ) @@ -2214,31 +2167,31 @@ int Track::getTCONum( const TrackContentObject * _tco ) * * We return the TCOs we find in order by time, earliest TCOs first. * - * \param _tco_c The list to contain the found trackContentObjects. - * \param _start The MIDI start time of the range. - * \param _end The MIDI endi time of the range. + * \param tcoV The list to contain the found trackContentObjects. + * \param start The MIDI start time of the range. + * \param end The MIDI endi time of the range. */ -void Track::getTCOsInRange( tcoVector & _tco_v, const MidiTime & _start, - const MidiTime & _end ) +void Track::getTCOsInRange( tcoVector & tcoV, const MidiTime & start, + const MidiTime & end ) { - for( tcoVector::iterator it_o = m_trackContentObjects.begin(); - it_o != m_trackContentObjects.end(); ++it_o ) + for( tcoVector::iterator itO = m_trackContentObjects.begin(); + itO != m_trackContentObjects.end(); ++itO ) { - TrackContentObject * tco = ( *it_o ); + TrackContentObject * tco = ( *itO ); int s = tco->startPosition(); int e = tco->endPosition(); - if( ( s <= _end ) && ( e >= _start ) ) + if( ( s <= end ) && ( e >= start ) ) { // ok, TCO is posated within given range // now let's search according position for TCO in list // -> list is ordered by TCO's position afterwards bool inserted = false; - for( tcoVector::iterator it = _tco_v.begin(); - it != _tco_v.end(); ++it ) + for( tcoVector::iterator it = tcoV.begin(); + it != tcoV.end(); ++it ) { if( ( *it )->startPosition() >= s ) { - _tco_v.insert( it, tco ); + tcoV.insert( it, tco ); inserted = true; break; } @@ -2246,7 +2199,7 @@ void Track::getTCOsInRange( tcoVector & _tco_v, const MidiTime & _start, if( inserted == false ) { // no TCOs found posated behind current TCO... - _tco_v.push_back( tco ); + tcoV.push_back( tco ); } } } @@ -2260,19 +2213,19 @@ void Track::getTCOsInRange( tcoVector & _tco_v, const MidiTime & _start, * First, we arrange to swap the positions of the two TCOs in the * trackContentObjects list. Then we swap their start times as well. * - * \param _tco_num1 The first TrackContentObject to swap. - * \param _tco_num2 The second TrackContentObject to swap. + * \param tcoNum1 The first TrackContentObject to swap. + * \param tcoNum2 The second TrackContentObject to swap. */ -void Track::swapPositionOfTCOs( int _tco_num1, int _tco_num2 ) +void Track::swapPositionOfTCOs( int tcoNum1, int tcoNum2 ) { - qSwap( m_trackContentObjects[_tco_num1], - m_trackContentObjects[_tco_num2] ); + qSwap( m_trackContentObjects[tcoNum1], + m_trackContentObjects[tcoNum2] ); - const MidiTime pos = m_trackContentObjects[_tco_num1]->startPosition(); + const MidiTime pos = m_trackContentObjects[tcoNum1]->startPosition(); - m_trackContentObjects[_tco_num1]->movePosition( - m_trackContentObjects[_tco_num2]->startPosition() ); - m_trackContentObjects[_tco_num2]->movePosition( pos ); + m_trackContentObjects[tcoNum1]->movePosition( + m_trackContentObjects[tcoNum2]->startPosition() ); + m_trackContentObjects[tcoNum2]->movePosition( pos ); } @@ -2280,19 +2233,19 @@ void Track::swapPositionOfTCOs( int _tco_num1, int _tco_num2 ) /*! \brief Move all the trackContentObjects after a certain time later by one bar. * - * \param _pos The time at which we want to insert the bar. + * \param pos The time at which we want to insert the bar. * \todo if we stepped through this list last to first, and the list was * 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::insertTact( const MidiTime & pos ) { - // we'll increase the position of every TCO, positioned behind _pos, by + // we'll increase the position of every TCO, positioned behind pos, by // one tact for( tcoVector::iterator it = m_trackContentObjects.begin(); it != m_trackContentObjects.end(); ++it ) { - if( ( *it )->startPosition() >= _pos ) + if( ( *it )->startPosition() >= pos ) { ( *it )->movePosition( (*it)->startPosition() + MidiTime::ticksPerTact() ); @@ -2305,16 +2258,16 @@ void Track::insertTact( const MidiTime & _pos ) /*! \brief Move all the trackContentObjects after a certain time earlier by one bar. * - * \param _pos The time at which we want to remove the bar. + * \param pos The time at which we want to remove the bar. */ -void Track::removeTact( const MidiTime & _pos ) +void Track::removeTact( const MidiTime & pos ) { - // we'll decrease the position of every TCO, positioned behind _pos, by + // we'll decrease the position of every TCO, positioned behind pos, by // one tact for( tcoVector::iterator it = m_trackContentObjects.begin(); it != m_trackContentObjects.end(); ++it ) { - if( ( *it )->startPosition() >= _pos ) + if( ( *it )->startPosition() >= pos ) { ( *it )->movePosition( qMax( ( *it )->startPosition() - MidiTime::ticksPerTact(), 0 ) ); @@ -2360,7 +2313,7 @@ void Track::toggleSolo() { const TrackContainer::TrackList & tl = m_trackContainer->tracks(); - bool solo_before = false; + bool soloBefore = false; for( TrackContainer::TrackList::const_iterator it = tl.begin(); it != tl.end(); ++it ) { @@ -2368,7 +2321,7 @@ void Track::toggleSolo() { if( ( *it )->m_soloModel.value() ) { - solo_before = true; + soloBefore = true; break; } } @@ -2381,7 +2334,7 @@ void Track::toggleSolo() if( solo ) { // save mute-state in case no track was solo before - if( !solo_before ) + if( !soloBefore ) { ( *it )->m_mutedBeforeSolo = ( *it )->isMuted(); } @@ -2391,7 +2344,7 @@ void Track::toggleSolo() ( *it )->m_soloModel.setValue( false ); } } - else if( !solo_before ) + else if( !soloBefore ) { ( *it )->setMuted( ( *it )->m_mutedBeforeSolo ); } @@ -2412,15 +2365,15 @@ void Track::toggleSolo() * The track View is handles the actual display of the track, including * displaying its various widgets and the track segments. * - * \param _track The track to display. - * \param _tcv The track Container View for us to be displayed in. + * \param track The track to display. + * \param tcv The track Container View for us to be displayed in. * \todo Is my description of these properties correct? */ -TrackView::TrackView( Track * _track, TrackContainerView * _tcv ) : - QWidget( _tcv->contentWidget() ), /*!< The Track Container View's content widget. */ +TrackView::TrackView( Track * track, TrackContainerView * tcv ) : + QWidget( tcv->contentWidget() ), /*!< The Track Container View's content widget. */ ModelView( NULL, this ), /*!< The model view of this track */ - m_track( _track ), /*!< The track we're displaying */ - m_trackContainerView( _tcv ), /*!< The track Container View we're displayed in */ + m_track( track ), /*!< The track we're displaying */ + m_trackContainerView( tcv ), /*!< The track Container View we're displayed in */ m_trackOperationsWidget( this ), /*!< Our trackOperationsWidget */ m_trackSettingsWidget( this ), /*!< Our trackSettingsWidget */ m_trackContentWidget( this ), /*!< Our trackContentWidget */ @@ -2484,9 +2437,9 @@ TrackView::~TrackView() /*! \brief Resize this track View. * - * \param _re the Resize Event to handle. + * \param re the Resize Event to handle. */ -void TrackView::resizeEvent( QResizeEvent * _re ) +void TrackView::resizeEvent( QResizeEvent * re ) { if( ConfigManager::inst()->value( "ui", "compacttrackbuttons" ).toInt() ) @@ -2552,11 +2505,11 @@ void TrackView::modelChanged() /*! \brief Start a drag event on this track View. * - * \param _dee the DragEnterEvent to start. + * \param dee the DragEnterEvent to start. */ -void TrackView::dragEnterEvent( QDragEnterEvent * _dee ) +void TrackView::dragEnterEvent( QDragEnterEvent * dee ) { - StringPairDrag::processDragEnterEvent( _dee, "track_" + + StringPairDrag::processDragEnterEvent( dee, "track_" + QString::number( m_track->type() ) ); } @@ -2569,12 +2522,12 @@ void TrackView::dragEnterEvent( QDragEnterEvent * _dee ) * If so, we decode the data from the drop event by just feeding it * back into the engine as a state. * - * \param _de the DropEvent to handle. + * \param de the DropEvent to handle. */ -void TrackView::dropEvent( QDropEvent * _de ) +void TrackView::dropEvent( QDropEvent * de ) { - QString type = StringPairDrag::decodeKey( _de ); - QString value = StringPairDrag::decodeValue( _de ); + QString type = StringPairDrag::decodeKey( de ); + QString value = StringPairDrag::decodeValue( de ); if( type == ( "track_" + QString::number( m_track->type() ) ) ) { // value contains our XML-data so simply create a @@ -2583,7 +2536,7 @@ void TrackView::dropEvent( QDropEvent * _de ) m_track->lock(); m_track->restoreState( dataFile.content().firstChild().toElement() ); m_track->unlock(); - _de->accept(); + de->accept(); } } @@ -2601,14 +2554,14 @@ void TrackView::dropEvent( QDropEvent * _de ) * * Otherwise we let the widget handle the mouse event as normal. * - * \param _me the MouseEvent to handle. + * \param me the MouseEvent to handle. */ -void TrackView::mousePressEvent( QMouseEvent * _me ) +void TrackView::mousePressEvent( QMouseEvent * me ) { // If previously dragged too small, restore on shift-leftclick if( height() < DEFAULT_TRACK_HEIGHT && - _me->modifiers() & Qt::ShiftModifier && - _me->button() == Qt::LeftButton ) + me->modifiers() & Qt::ShiftModifier && + me->button() == Qt::LeftButton ) { setFixedHeight( DEFAULT_TRACK_HEIGHT ); m_track->setHeight( DEFAULT_TRACK_HEIGHT ); @@ -2619,16 +2572,16 @@ void TrackView::mousePressEvent( QMouseEvent * _me ) "compacttrackbuttons" ).toInt()==1 ? DEFAULT_SETTINGS_WIDGET_WIDTH_COMPACT + TRACK_OP_WIDTH_COMPACT : DEFAULT_SETTINGS_WIDGET_WIDTH + TRACK_OP_WIDTH; - if( m_trackContainerView->allowRubberband() == true && _me->x() > widgetTotal ) + if( m_trackContainerView->allowRubberband() == true && me->x() > widgetTotal ) { - QWidget::mousePressEvent( _me ); + QWidget::mousePressEvent( me ); } - else if( _me->button() == Qt::LeftButton ) + else if( me->button() == Qt::LeftButton ) { - if( _me->modifiers() & Qt::ShiftModifier ) + if( me->modifiers() & Qt::ShiftModifier ) { m_action = ResizeTrack; - QCursor::setPos( mapToGlobal( QPoint( _me->x(), + QCursor::setPos( mapToGlobal( QPoint( me->x(), height() ) ) ); QCursor c( Qt::SizeVerCursor); QApplication::setOverrideCursor( c ); @@ -2644,11 +2597,11 @@ void TrackView::mousePressEvent( QMouseEvent * _me ) m_trackOperationsWidget.update(); } - _me->accept(); + me->accept(); } else { - QWidget::mousePressEvent( _me ); + QWidget::mousePressEvent( me ); } } @@ -2669,32 +2622,33 @@ void TrackView::mousePressEvent( QMouseEvent * _me ) * Likewise if we've started a resize process, handle this too, making * sure that we never go below the minimum track height. * - * \param _me the MouseEvent to handle. + * \param me the MouseEvent to handle. */ -void TrackView::mouseMoveEvent( QMouseEvent * _me ) +void TrackView::mouseMoveEvent( QMouseEvent * me ) { int widgetTotal = ConfigManager::inst()->value( "ui", "compacttrackbuttons" ).toInt()==1 ? DEFAULT_SETTINGS_WIDGET_WIDTH_COMPACT + TRACK_OP_WIDTH_COMPACT : DEFAULT_SETTINGS_WIDGET_WIDTH + TRACK_OP_WIDTH; - if( m_trackContainerView->allowRubberband() == true && _me->x() > widgetTotal ) + if( m_trackContainerView->allowRubberband() == true && me->x() > widgetTotal ) { - QWidget::mouseMoveEvent( _me ); + QWidget::mouseMoveEvent( me ); } else if( m_action == MoveTrack ) { // look which track-widget the mouse-cursor is over - const int y_pos = m_trackContainerView->contentWidget()->mapFromGlobal( _me->globalPos() ).y(); - const TrackView * track_at_y = m_trackContainerView->trackViewAt( y_pos ); + const int yPos = + m_trackContainerView->contentWidget()->mapFromGlobal( me->globalPos() ).y(); + const TrackView * trackAtY = m_trackContainerView->trackViewAt( yPos ); // debug code -// qDebug( "y position %d", y_pos ); +// qDebug( "y position %d", yPos ); // a track-widget not equal to ourself? - if( track_at_y != NULL && track_at_y != this ) + if( trackAtY != NULL && trackAtY != this ) { // then move us up/down there! - if( _me->y() < 0 ) + if( me->y() < 0 ) { m_trackContainerView->moveTrackViewUp( this ); } @@ -2706,7 +2660,7 @@ void TrackView::mouseMoveEvent( QMouseEvent * _me ) } else if( m_action == ResizeTrack ) { - setFixedHeight( qMax( _me->y(), MINIMAL_TRACK_HEIGHT ) ); + setFixedHeight( qMax( me->y(), MINIMAL_TRACK_HEIGHT ) ); m_trackContainerView->realignTracks(); m_track->setHeight( height() ); } @@ -2721,9 +2675,9 @@ void TrackView::mouseMoveEvent( QMouseEvent * _me ) /*! \brief Handle a mouse release event on this track View. * - * \param _me the MouseEvent to handle. + * \param me the MouseEvent to handle. */ -void TrackView::mouseReleaseEvent( QMouseEvent * _me ) +void TrackView::mouseReleaseEvent( QMouseEvent * me ) { m_action = NoAction; while( QApplication::overrideCursor() != NULL ) @@ -2732,7 +2686,7 @@ void TrackView::mouseReleaseEvent( QMouseEvent * _me ) } m_trackOperationsWidget.update(); - QWidget::mouseReleaseEvent( _me ); + QWidget::mouseReleaseEvent( me ); } @@ -2740,9 +2694,9 @@ void TrackView::mouseReleaseEvent( QMouseEvent * _me ) /*! \brief Repaint this track View. * - * \param _pe the PaintEvent to start. + * \param pe the PaintEvent to start. */ -void TrackView::paintEvent( QPaintEvent * _pe ) +void TrackView::paintEvent( QPaintEvent * pe ) { QStyleOption opt; opt.initFrom( this ); @@ -2755,22 +2709,18 @@ void TrackView::paintEvent( QPaintEvent * _pe ) /*! \brief Create a TrackContentObject View in this track View. * - * \param _tco the TrackContentObject to create the view for. + * \param tco the TrackContentObject to create the view for. * \todo is this a good description for what this method does? */ -void TrackView::createTCOView( TrackContentObject * _tco ) +void TrackView::createTCOView( TrackContentObject * tco ) { - TrackContentObjectView * tv = _tco->createView( this ); - if( _tco->getSelectViewOnCreate() == true ) + TrackContentObjectView * tv = tco->createView( this ); + if( tco->getSelectViewOnCreate() == true ) { tv->setSelected( true ); } - _tco->selectViewOnCreate( false ); + tco->selectViewOnCreate( false ); } - - - - diff --git a/src/core/VstSyncController.cpp b/src/core/VstSyncController.cpp index 1e1294c32..a28b9adb1 100644 --- a/src/core/VstSyncController.cpp +++ b/src/core/VstSyncController.cpp @@ -30,12 +30,7 @@ #include "lmmsconfig.h" #include "Mixer.h" #include "VstSyncController.h" - -#ifdef LMMS_BUILD_WIN32 -#ifndef USE_QT_SHMEM -#define USE_QT_SHMEM -#endif -#endif +#include "RemotePlugin.h" #ifndef USE_QT_SHMEM #include diff --git a/src/core/audio/AudioJack.cpp b/src/core/audio/AudioJack.cpp index 513898983..b491ea826 100644 --- a/src/core/audio/AudioJack.cpp +++ b/src/core/audio/AudioJack.cpp @@ -51,7 +51,6 @@ AudioJack::AudioJack( bool & _success_ful, Mixer* _mixer ) : _mixer ), m_client( NULL ), m_active( false ), - m_stopSemaphore( 1 ), m_tempOutBufs( new jack_default_audio_sample_t *[channels()] ), m_outBuf( new surroundSampleFrame[mixer()->framesPerPeriod()] ), m_framesDoneInCurBuf( 0 ), @@ -60,8 +59,6 @@ AudioJack::AudioJack( bool & _success_ful, Mixer* _mixer ) : _success_ful = initJackClient(); if( _success_ful ) { - m_stopSemaphore.acquire(); - connect( this, SIGNAL( zombified() ), this, SLOT( restartAfterZombified() ), Qt::QueuedConnection ); @@ -74,8 +71,6 @@ AudioJack::AudioJack( bool & _success_ful, Mixer* _mixer ) : AudioJack::~AudioJack() { - m_stopSemaphore.release(); - #ifdef AUDIO_PORT_SUPPORT while( m_portMap.size() ) { @@ -249,7 +244,6 @@ void AudioJack::startProcessing() void AudioJack::stopProcessing() { - m_stopSemaphore.acquire(); } @@ -390,7 +384,6 @@ int AudioJack::processCallback( jack_nframes_t _nframes, void * _udata ) if( !m_framesToDoInCurBuf ) { m_stopped = true; - m_stopSemaphore.release(); } m_framesDoneInCurBuf = 0; } @@ -446,7 +439,7 @@ AudioJack::setupWidget::setupWidget( QWidget * _parent ) : cn_lbl->setFont( pointSize<7>( cn_lbl->font() ) ); cn_lbl->setGeometry( 10, 40, 160, 10 ); - LcdSpinBoxModel * m = new LcdSpinBoxModel( /* this */ ); + LcdSpinBoxModel * m = new LcdSpinBoxModel( /* this */ ); m->setRange( DEFAULT_CHANNELS, SURROUND_CHANNELS ); m->setStep( 2 ); m->setValue( ConfigManager::inst()->value( "audiojack", @@ -483,4 +476,3 @@ void AudioJack::setupWidget::saveSettings() #endif - diff --git a/src/core/main.cpp b/src/core/main.cpp index 2502058c2..5313811d1 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -116,6 +116,7 @@ int main( int argc, char * * argv ) bool core_only = false; bool fullscreen = true; bool exit_after_import = false; + bool allow_root = false; QString file_to_load, file_to_save, file_to_import, render_out, profilerOutputFile; for( int i = 1; i < argc; ++i ) @@ -127,6 +128,10 @@ int main( int argc, char * * argv ) { core_only = true; } + else if( argc > i && ( QString( argv[i] ) == "--allowroot" ) ) + { + allow_root = true; + } else if( argc > i && QString( argv[i] ) == "-geometry" ) { // option -geometry is filtered by Qt later, @@ -137,6 +142,14 @@ int main( int argc, char * * argv ) } } +#ifndef LMMS_BUILD_WIN32 + if ( ( getuid() == 0 || geteuid() == 0 ) && !allow_root ) + { + printf("LMMS cannot be run as root.\nUse \"--allowroot\" to override.\n\n"); + return(EXIT_FAILURE); + } +#endif + QCoreApplication * app = core_only ? new QCoreApplication( argc, argv ) : new QApplication( argc, argv ) ; @@ -191,10 +204,12 @@ int main( int argc, char * * argv ) "-x, --oversampling specify oversampling\n" " possible values: 1, 2, 4, 8\n" " default: 2\n" + "-a, --float 32bit float bit depth\n" "-u, --upgrade [out] upgrade file and save as \n" " standard out is used if no output file is specifed\n" "-d, --dump dump XML of compressed file \n" "-v, --version show version information and exit.\n" + " --allowroot bypass root user startup check (use with caution).\n" "-h, --help show this usage information and exit.\n\n", LMMS_VERSION ); return( EXIT_SUCCESS ); @@ -217,6 +232,17 @@ int main( int argc, char * * argv ) } return( EXIT_SUCCESS ); } + else if( argc > i && QString( argv[i] ) == "--allowroot" ) + { + // Ignore, processed earlier +#ifdef LMMS_BUILD_WIN32 + if ( allow_root ) + { + printf( "\nOption \"--allowroot\" will be ignored on this platform.\n\n" ); + } +#endif + + } else if( argc > i && ( QString( argv[i] ) == "--dump" || QString( argv[i] ) == "-d" ) ) { @@ -296,6 +322,12 @@ int main( int argc, char * * argv ) } ++i; } + else if ( argc > i && + ( QString( argv[i] ) =="--float" || + QString( argv[i] ) == "-a" ) ) + { + os.depth = ProjectRenderer::Depth_32Bit; + } else if( argc > i && ( QString( argv[i] ) == "--interpolation" || QString( argv[i] ) == "-i" ) ) diff --git a/src/gui/FileBrowser.cpp b/src/gui/FileBrowser.cpp index 704264b62..e7d946acc 100644 --- a/src/gui/FileBrowser.cpp +++ b/src/gui/FileBrowser.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include "FileBrowser.h" #include "BBTrackContainer.h" @@ -458,11 +459,25 @@ void FileBrowserTreeWidget::mousePressEvent(QMouseEvent * me ) m_previewPlayHandle = s; delete tf; } + else if( f->extension ()== "xiz" && ! pluginFactory->pluginSupportingExtension(f->extension()).isNull() ) + { + m_previewPlayHandle = new PresetPreviewPlayHandle( f->fullName(), f->handling() == FileItem::LoadByPlugin ); + } else if( f->type() != FileItem::VstPluginFile && ( f->handling() == FileItem::LoadAsPreset || f->handling() == FileItem::LoadByPlugin ) ) { - m_previewPlayHandle = new PresetPreviewPlayHandle( f->fullName(), f->handling() == FileItem::LoadByPlugin ); + DataFile dataFile( f->fullName() ); + if( !dataFile.validate( f->extension() ) ) + { + QMessageBox::warning( 0, tr ( "Error" ), + f->fullName() + " " + tr( "does not appear to be a valid" ) + " " + f->extension() + + " " + tr( "file" ), + QMessageBox::Ok, QMessageBox::NoButton ); + m_pphMutex.unlock(); + return; + } + m_previewPlayHandle = new PresetPreviewPlayHandle( f->fullName(), f->handling() == FileItem::LoadByPlugin, &dataFile ); } if( m_previewPlayHandle != NULL ) { @@ -573,7 +588,7 @@ void FileBrowserTreeWidget::handleFile(FileItem * f, InstrumentTrack * it ) switch( f->handling() ) { case FileItem::LoadAsProject: - if( gui->mainWindow()->mayChangeProject() ) + if( gui->mainWindow()->mayChangeProject(true) ) { Engine::getSong()->loadProject( f->fullName() ); } @@ -604,7 +619,7 @@ void FileBrowserTreeWidget::handleFile(FileItem * f, InstrumentTrack * it ) case FileItem::ImportAsProject: if( f->type() == FileItem::FlpFile && - !gui->mainWindow()->mayChangeProject() ) + !gui->mainWindow()->mayChangeProject(true) ) { break; } diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index b7f5c1443..154133882 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -75,7 +75,8 @@ MainWindow::MainWindow() : m_templatesMenu( NULL ), m_recentlyOpenedProjectsMenu( NULL ), m_toolsMenu( NULL ), - m_autoSaveTimer( this ) + m_autoSaveTimer( this ), + m_viewMenu( NULL ) { setAttribute( Qt::WA_DeleteOnClose ); @@ -274,6 +275,12 @@ void MainWindow::finalize() SLOT( exportProjectTracks() ), Qt::CTRL + Qt::SHIFT + Qt::Key_E ); + project_menu->addAction( embed::getIconPixmap( "midi_file" ), + tr( "E&xport MIDI..." ), + Engine::getSong(), + SLOT( exportProjectMidi() ), + Qt::CTRL + Qt::Key_M ); + project_menu->addSeparator(); project_menu->addAction( embed::getIconPixmap( "exit" ), tr( "&Quit" ), qApp, SLOT( closeAllWindows() ), @@ -295,6 +302,13 @@ void MainWindow::finalize() tr( "Settings" ), this, SLOT( showSettingsDialog() ) ); + m_viewMenu = new QMenu( this ); + menuBar()->addMenu( m_viewMenu )->setText( tr( "&View" ) ); + connect( m_viewMenu, SIGNAL( aboutToShow() ), + this, SLOT( updateViewMenu() ) ); + connect( m_viewMenu, SIGNAL(triggered(QAction*)), this, + SLOT(updateConfig(QAction*))); + m_toolsMenu = new QMenu( this ); for( const Plugin::Descriptor* desc : pluginFactory->descriptors(Plugin::Tool) ) @@ -598,9 +612,10 @@ void MainWindow::resetWindowTitle() -bool MainWindow::mayChangeProject() +bool MainWindow::mayChangeProject(bool stopPlayback) { - Engine::getSong()->stop(); + if( stopPlayback ) + Engine::getSong()->stop(); if( !Engine::getSong()->isModified() ) { @@ -713,7 +728,7 @@ void MainWindow::enterWhatsThisMode() void MainWindow::createNewProject() { - if( mayChangeProject() ) + if( mayChangeProject(true) ) { Engine::getSong()->createNewProject(); } @@ -724,7 +739,7 @@ void MainWindow::createNewProject() void MainWindow::createNewProjectFromTemplate( QAction * _idx ) { - if( m_templatesMenu != NULL && mayChangeProject() ) + if( m_templatesMenu != NULL && mayChangeProject(true) ) { QString dir_base = m_templatesMenu->actions().indexOf( _idx ) >= m_custom_templates_count ? @@ -740,7 +755,7 @@ void MainWindow::createNewProjectFromTemplate( QAction * _idx ) void MainWindow::openProject() { - if( mayChangeProject() ) + if( mayChangeProject(false) ) { FileDialog ofd( this, tr( "Open Project" ), "", tr( "LMMS (*.mmp *.mmpz)" ) ); @@ -749,6 +764,8 @@ void MainWindow::openProject() if( ofd.exec () == QDialog::Accepted && !ofd.selectedFiles().isEmpty() ) { + Engine::getSong()->stop(); + setCursor( Qt::WaitCursor ); Engine::getSong()->loadProject( ofd.selectedFiles()[0] ); @@ -776,7 +793,7 @@ void MainWindow::updateRecentlyOpenedProjectsMenu() void MainWindow::openRecentlyOpenedProject( QAction * _action ) { - if ( mayChangeProject() ) + if ( mayChangeProject(true) ) { const QString & f = _action->text(); setCursor( Qt::WaitCursor ); @@ -808,8 +825,8 @@ bool MainWindow::saveProject() bool MainWindow::saveProjectAs() { VersionedSaveDialog sfd( this, tr( "Save Project" ), "", - tr( "LMMS Project (*.mmpz *.mmp);;" - "LMMS Project Template (*.mpt)" ) ); + tr( "LMMS Project" ) + " (*.mmpz *.mmp);;" + + tr( "LMMS Project Template" ) + " (*.mpt)" ); QString f = Engine::getSong()->projectFileName(); if( f != "" ) { @@ -824,8 +841,13 @@ bool MainWindow::saveProjectAs() if( sfd.exec () == FileDialog::Accepted && !sfd.selectedFiles().isEmpty() && sfd.selectedFiles()[0] != "" ) { + QString fname = sfd.selectedFiles()[0] ; + if( sfd.selectedNameFilter().contains( "(*.mpt)" ) && !sfd.selectedFiles()[0].endsWith( ".mpt" ) ) + { + fname += ".mpt"; + } Engine::getSong()->guiSaveProjectAs( - sfd.selectedFiles()[0] ); + fname ); return( true ); } return( false ); @@ -991,6 +1013,110 @@ void MainWindow::toggleFxMixerWin() } +void MainWindow::updateViewMenu() +{ + m_viewMenu->clear(); + // TODO: get current visibility for these and indicate in menu? + // Not that it's straight visible <-> invisible, more like + // not on top -> top <-> invisible + m_viewMenu->addAction(embed::getIconPixmap( "songeditor" ), + tr( "Song Editor" ) + " (F5)", + this, SLOT( toggleSongEditorWin() ) + ); + m_viewMenu->addAction(embed::getIconPixmap( "bb_track" ), + tr( "Pattern Editor" ) + " (F6)", + this, SLOT( toggleBBEditorWin() ) + ); + m_viewMenu->addAction(embed::getIconPixmap( "piano" ), + tr( "Piano Roll" ) + " (F7)", + this, SLOT( togglePianoRollWin() ) + ); + m_viewMenu->addAction(embed::getIconPixmap( "automation" ), + tr( "Automation Editor" ) + " (F8)", + this, + SLOT( toggleAutomationEditorWin()) + ); + m_viewMenu->addAction(embed::getIconPixmap( "fx_mixer" ), + tr( "FX Mixer" ) + " (F9)", + this, SLOT( toggleFxMixerWin() ) + ); + m_viewMenu->addAction(embed::getIconPixmap( "project_notes" ), + tr( "Project Notes" ) + " (F10)", + this, SLOT( toggleProjectNotesWin() ) + ); + m_viewMenu->addAction(embed::getIconPixmap( "controller" ), + tr( "Show/hide controller rack" ) + + " (F11)", + this, SLOT( toggleControllerRack() ) + ); + + m_viewMenu->addSeparator(); + + // Here we should put all look&feel -stuff from configmanager + // that is safe to change on the fly. There is probably some + // more elegant way to do this. + QAction *qa; + qa = new QAction(tr( "Volume as dBV" ), this); + qa->setData("displaydbv"); + qa->setCheckable( true ); + qa->setChecked( ConfigManager::inst()->value( "app", "displaydbv" ). + toInt() ? true : false ); + m_viewMenu->addAction(qa); + + // Maybe this is impossible? + /* qa = new QAction(tr( "Tooltips" ), this); + qa->setData("tooltips"); + qa->setCheckable( true ); + qa->setChecked( ConfigManager::inst()->value( "tooltips", "disabled" ). + toInt() ? false : true ); + m_viewMenu->addAction(qa); + */ + + // Should be doable. + qa = new QAction(tr( "Smooth scroll" ), this); + qa->setData("smoothscroll"); + qa->setCheckable( true ); + qa->setChecked( ConfigManager::inst()->value( "ui", "smoothscroll" ). + toInt() ? true : false ); + m_viewMenu->addAction(qa); + + // Not yet. + /* qa = new QAction(tr( "One instrument track window" ), this); + qa->setData("oneinstrument"); + qa->setCheckable( true ); + qa->setChecked( ConfigManager::inst()->value( "ui", "oneinstrumenttrackwindow" ). + toInt() ? true : false ); + m_viewMenu->addAction(qa); + */ +} + + +void MainWindow::updateConfig( QAction * _who ) +{ + QString tag = _who->data().toString(); + bool checked = _who->isChecked(); + + if( tag == "displaydbv" ) + { + ConfigManager::inst()->setValue( "app", "displaydbv", + QString::number(checked) ); + } + else if ( tag == "tooltips" ) + { + ConfigManager::inst()->setValue( "tooltips", "disabled", + QString::number(!checked) ); + } + else if ( tag == "smoothscroll" ) + { + ConfigManager::inst()->setValue( "ui", "smoothscroll", + QString::number(checked) ); + } + else if ( tag == "oneinstrument" ) + { + ConfigManager::inst()->setValue( "ui", "oneinstrumenttrackwindow", + QString::number(checked) ); + } +} void MainWindow::toggleControllerRack() @@ -1055,7 +1181,7 @@ void MainWindow::redo() void MainWindow::closeEvent( QCloseEvent * _ce ) { - if( mayChangeProject() ) + if( mayChangeProject(true) ) { // delete recovery file QFile::remove(ConfigManager::inst()->recoveryFile()); diff --git a/src/gui/SetupDialog.cpp b/src/gui/SetupDialog.cpp index b3450e700..91984f696 100644 --- a/src/gui/SetupDialog.cpp +++ b/src/gui/SetupDialog.cpp @@ -685,9 +685,18 @@ SetupDialog::SetupDialog( ConfigTabs _tab_to_open ) : asw_layout->addWidget( audioWidget ); m_audioInterfaces->addItem( it.key() ); } - m_audioInterfaces->setCurrentIndex( m_audioInterfaces->findText( - tr( Engine::mixer()->audioDevName().toLatin1() ) ) ); - m_audioIfaceSetupWidgets[Engine::mixer()->audioDevName()]->show(); + + QString audioDevName = + ConfigManager::inst()->value( "mixer", "audiodev" ); + if( audioDevName.length() == 0 ) + { + audioDevName = Engine::mixer()->audioDevName(); + ConfigManager::inst()->setValue( + "mixer", "audiodev", audioDevName ); + } + m_audioInterfaces-> + setCurrentIndex( m_audioInterfaces->findText( audioDevName ) ); + m_audioIfaceSetupWidgets[audioDevName]->show(); connect( m_audioInterfaces, SIGNAL( activated( const QString & ) ), this, SLOT( audioInterfaceChanged( const QString & ) ) ); @@ -766,9 +775,17 @@ SetupDialog::SetupDialog( ConfigTabs _tab_to_open ) : m_midiInterfaces->addItem( it.key() ); } - m_midiInterfaces->setCurrentIndex( m_midiInterfaces->findText( - tr( Engine::mixer()->midiClientName().toLatin1() ) ) ); - m_midiIfaceSetupWidgets[Engine::mixer()->midiClientName()]->show(); + QString midiDevName = + ConfigManager::inst()->value( "mixer", "mididev" ); + if( midiDevName.length() == 0 ) + { + midiDevName = Engine::mixer()->midiClientName(); + ConfigManager::inst()->setValue( + "mixer", "mididev", midiDevName ); + } + m_midiInterfaces->setCurrentIndex( + m_midiInterfaces->findText( midiDevName ) ); + m_midiIfaceSetupWidgets[midiDevName]->show(); connect( m_midiInterfaces, SIGNAL( activated( const QString & ) ), this, SLOT( midiInterfaceChanged( const QString & ) ) ); @@ -1373,5 +1390,3 @@ void SetupDialog::displayMIDIHelp() - - diff --git a/src/gui/TimeLineWidget.cpp b/src/gui/TimeLineWidget.cpp index 4ab508c9c..870d7288d 100644 --- a/src/gui/TimeLineWidget.cpp +++ b/src/gui/TimeLineWidget.cpp @@ -52,19 +52,19 @@ QPixmap * TimeLineWidget::s_posMarkerPixmap = NULL; QPixmap * TimeLineWidget::s_loopPointBeginPixmap = NULL; QPixmap * TimeLineWidget::s_loopPointEndPixmap = NULL; -TimeLineWidget::TimeLineWidget( const int _xoff, const int _yoff, const float _ppt, - Song::playPos & _pos, const MidiTime & _begin, - QWidget * _parent ) : - QWidget( _parent ), +TimeLineWidget::TimeLineWidget( const int xoff, const int yoff, const float ppt, + Song::PlayPos & pos, const MidiTime & begin, + QWidget * parent ) : + QWidget( parent ), m_autoScroll( AutoScrollEnabled ), m_loopPoints( LoopPointsDisabled ), m_behaviourAtStop( BackToZero ), m_changedPosition( true ), - m_xOffset( _xoff ), + m_xOffset( xoff ), m_posMarkerX( 0 ), - m_ppt( _ppt ), - m_pos( _pos ), - m_begin( _begin ), + m_ppt( ppt ), + m_pos( pos ), + m_begin( begin ), m_savedPos( -1 ), m_hint( NULL ), m_action( NoAction ), @@ -95,17 +95,17 @@ TimeLineWidget::TimeLineWidget( const int _xoff, const int _yoff, const float _p } setAttribute( Qt::WA_OpaquePaintEvent, true ); - move( 0, _yoff ); + move( 0, yoff ); setFixedHeight( s_timeLinePixmap->height() ); m_xOffset -= s_posMarkerPixmap->width() / 2; m_pos.m_timeLine = this; - QTimer * update_timer = new QTimer( this ); - connect( update_timer, SIGNAL( timeout() ), + QTimer * updateTimer = new QTimer( this ); + connect( updateTimer, SIGNAL( timeout() ), this, SLOT( updatePosition() ) ); - update_timer->start( 50 ); + updateTimer->start( 50 ); } @@ -401,7 +401,3 @@ void TimeLineWidget::mouseReleaseEvent( QMouseEvent* event ) - - - - diff --git a/src/gui/TrackContainerView.cpp b/src/gui/TrackContainerView.cpp index 7df7e3039..e3471c444 100644 --- a/src/gui/TrackContainerView.cpp +++ b/src/gui/TrackContainerView.cpp @@ -238,7 +238,7 @@ void TrackContainerView::deleteTrackView( TrackView * _tv ) removeTrackView( _tv ); delete _tv; - delete t; + t->deleteLater(); } @@ -377,7 +377,7 @@ void TrackContainerView::dropEvent( QDropEvent * _de ) else if( type == "projectfile") { - if( gui->mainWindow()->mayChangeProject() ) + if( gui->mainWindow()->mayChangeProject(true) ) { Engine::getSong()->loadProject( value ); } diff --git a/src/gui/editors/AutomationEditor.cpp b/src/gui/editors/AutomationEditor.cpp index bde69e950..3146d49b1 100644 --- a/src/gui/editors/AutomationEditor.cpp +++ b/src/gui/editors/AutomationEditor.cpp @@ -447,7 +447,6 @@ void AutomationEditor::mousePressEvent( QMouseEvent* mouseEvent ) { return; } - if( mouseEvent->y() > TOP_MARGIN ) { float level = getLevel( mouseEvent->y() ); @@ -493,6 +492,7 @@ void AutomationEditor::mousePressEvent( QMouseEvent* mouseEvent ) if( mouseEvent->button() == Qt::LeftButton && m_editMode == DRAW ) { + m_pattern->addJournalCheckPoint(); // Connect the dots if( mouseEvent->modifiers() & Qt::ShiftModifier ) { @@ -537,6 +537,7 @@ void AutomationEditor::mousePressEvent( QMouseEvent* mouseEvent ) m_editMode == DRAW ) || m_editMode == ERASE ) { + m_pattern->addJournalCheckPoint(); // erase single value if( it != time_map.end() ) { @@ -566,6 +567,7 @@ void AutomationEditor::mousePressEvent( QMouseEvent* mouseEvent ) else if( mouseEvent->button() == Qt::LeftButton && m_editMode == MOVE ) { + m_pattern->addJournalCheckPoint(); // move selection (including selected values) // save position where move-process began @@ -1312,8 +1314,9 @@ void AutomationEditor::paintEvent(QPaintEvent * pe ) m_leftRightScroll->setPageStep( l ); } - if( validPattern() ) + if( validPattern() && GuiApplication::instance()->automationEditor()->hasFocus() ) { + drawCross( p ); } @@ -1660,6 +1663,7 @@ void AutomationEditor::setProgressionType(AutomationPattern::ProgressionTypes ty { if (validPattern()) { + m_pattern->addJournalCheckPoint(); QMutexLocker m(&m_patternMutex); m_pattern->setProgressionType(type); Engine::getSong()->setModified(); @@ -1799,6 +1803,7 @@ void AutomationEditor::cutSelectedValues() return; } + m_pattern->addJournalCheckPoint(); m_valuesToCopy.clear(); timeMap selected_values; @@ -1828,6 +1833,7 @@ void AutomationEditor::pasteValues() QMutexLocker m( &m_patternMutex ); if( validPattern() && !m_valuesToCopy.isEmpty() ) { + m_pattern->addJournalCheckPoint(); for( timeMap::iterator it = m_valuesToCopy.begin(); it != m_valuesToCopy.end(); ++it ) { @@ -1854,6 +1860,7 @@ void AutomationEditor::deleteSelectedValues() return; } + m_pattern->addJournalCheckPoint(); timeMap selected_values; getSelectedValues( selected_values ); diff --git a/src/gui/editors/BBEditor.cpp b/src/gui/editors/BBEditor.cpp index db14eecf6..953cefa91 100644 --- a/src/gui/editors/BBEditor.cpp +++ b/src/gui/editors/BBEditor.cpp @@ -102,7 +102,9 @@ BBEditor::BBEditor( BBTrackContainer* tc ) : m_toolBar->addAction(embed::getIconPixmap("step_btn_remove"), tr("Remove steps"), m_trackContainerView, SLOT(removeSteps())); m_toolBar->addAction(embed::getIconPixmap("step_btn_add"), tr("Add steps"), - m_trackContainerView, SLOT(addSteps())); + m_trackContainerView, SLOT( addSteps())); + m_toolBar->addAction( embed::getIconPixmap( "step_btn_duplicate" ), tr( "Clone Steps" ), + m_trackContainerView, SLOT( cloneSteps() ) ); m_toolBar->addSeparator(); connect( &tc->m_bbComboBoxModel, SIGNAL( dataChanged() ), @@ -170,17 +172,12 @@ BBTrackContainerView::BBTrackContainerView(BBTrackContainer* tc) : void BBTrackContainerView::addSteps() { - TrackContainer::TrackList tl = model()->tracks(); + makeSteps( false ); +} - for( TrackContainer::TrackList::iterator it = tl.begin(); - it != tl.end(); ++it ) - { - if( ( *it )->type() == Track::InstrumentTrack ) - { - Pattern* p = static_cast( ( *it )->getTCO( m_bbtc->currentBB() ) ); - p->addSteps(); - } - } +void BBTrackContainerView::cloneSteps() +{ + makeSteps( true ); } @@ -264,3 +261,27 @@ void BBTrackContainerView::updatePosition() //realignTracks(); emit positionChanged( m_currentPosition ); } + + + + +void BBTrackContainerView::makeSteps( bool clone ) +{ + TrackContainer::TrackList tl = model()->tracks(); + + for( TrackContainer::TrackList::iterator it = tl.begin(); + it != tl.end(); ++it ) + { + if( ( *it )->type() == Track::InstrumentTrack ) + { + Pattern* p = static_cast( ( *it )->getTCO( m_bbtc->currentBB() ) ); + if( clone ) + { + p->cloneSteps(); + } else + { + p->addSteps(); + } + } + } +} diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index c14b6b930..5a6805657 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -862,6 +862,9 @@ void PianoRoll::shiftPos( int amount ) //shift notes pos by amount } } + m_pattern->rearrangeAllNotes(); + m_pattern->dataChanged(); + // we modified the song update(); gui->songEditor()->update(); @@ -1535,7 +1538,7 @@ void PianoRoll::mousePressEvent(QMouseEvent * me ) //put notes from vector into piano roll for( int i = 0; i < newNotes.size(); ++i) { - Note * newNote = m_pattern->addNote( newNotes[i] ); + Note * newNote = m_pattern->addNote( newNotes[i], false ); newNote->setSelected( false ); } @@ -1657,13 +1660,11 @@ void PianoRoll::mouseDoubleClickEvent(QMouseEvent * me ) notes += m_pattern->notes(); // go through notes to figure out which one we want to change + bool altPressed = me->modifiers() & Qt::AltModifier; NoteVector nv; foreach( Note * i, notes ) { - if( i->pos().getTicks() >= ticks_start - && i->pos().getTicks() <= ticks_end - && i->length().getTicks() != 0 - && ( i->selected() || ! isSelection() ) ) + if( i->withinRange( ticks_start, ticks_end ) || ( i->selected() && !altPressed ) ) { nv += i; } @@ -2077,27 +2078,22 @@ void PianoRoll::mouseMoveEvent( QMouseEvent * me ) } } - - - // loop through vector - bool on_note = false; - bool use_selection = isSelection(); + // When alt is pressed we only edit the note under the cursor + bool altPressed = me->modifiers() & Qt::AltModifier; + // We iterate from last note in pattern to the first, + // chronologically NoteVector::ConstIterator it = notes.begin()+notes.size()-1; for( int i = 0; i < notes.size(); ++i ) { - Note * n = *it; - if( n->pos().getTicks() >= ticks_start - && n->pos().getTicks() <= ticks_end - && n->length().getTicks() != 0 - && ( n->selected() || ! use_selection ) ) + Note* n = *it; + + bool isUnderPosition = n->withinRange( ticks_start, ticks_end ); + // Play note under the cursor + if ( isUnderPosition ) { testPlayNote( n ); } + // If note is the one under the cursor or is selected when alt is + // not pressed + if ( isUnderPosition || ( n->selected() && !altPressed ) ) { - on_note = true; - m_pattern->dataChanged(); - - // play the note so that the user can tell how loud it is - // and where it is panned - testPlayNote( n ); - if( m_noteEditMode == NoteEditVolume ) { n->setVolume( vol ); @@ -2114,31 +2110,23 @@ void PianoRoll::mouseMoveEvent( QMouseEvent * me ) m_pattern->instrumentTrack()->processInEvent( evt ); } } - else + else if( n->isPlaying() ) { - if( n->isPlaying() ) - { - // mouse not over this note, stop playing it. - m_pattern->instrumentTrack()->pianoModel()->handleKeyRelease( n->key() ); + // mouse not over this note, stop playing it. + m_pattern->instrumentTrack()->pianoModel()->handleKeyRelease( n->key() ); - n->setIsPlaying( false ); - } + n->setIsPlaying( false ); } - // set textfloat visible if we're on a note - if( on_note ) - { - s_textFloat->moveGlobal( this, QPoint( me->x() + 4, me->y() + 16 ) ); - s_textFloat->show(); - } - else - { - s_textFloat->hide(); - } --it; - } + + // Emit pattern has changed + m_pattern->dataChanged(); + // Show the new volume value + s_textFloat->moveGlobal( this, QPoint( me->x() + 4, me->y() + 16 ) ); + s_textFloat->show(); } else if( me->buttons() == Qt::NoButton && m_editMode == ModeDraw ) @@ -2460,6 +2448,8 @@ void PianoRoll::dragNotes( int x, int y, bool alt, bool shift, bool ctrl ) // will be our iterator in the following loop NoteVector::ConstIterator it = notes.begin(); + + int sNotes = selectionCount(); while( it != notes.end() ) { Note *note = *it; @@ -2468,8 +2458,9 @@ void PianoRoll::dragNotes( int x, int y, bool alt, bool shift, bool ctrl ) // When resizing notes: // If shift is pressed we resize and rearrange only the selected notes // If shift + ctrl then we also rearrange all posterior notes (sticky) + // If shift is pressed but only one note is selected, apply sticky if( m_action == ActionResizeNote && shift && - ( note->selected() || ctrl ) ) + ( note->selected() || ctrl || sNotes == 1 ) ) { int shifted_pos = note->oldPos().getTicks() + shift_offset; if( shifted_pos && pos == shift_ref_pos ) @@ -3162,14 +3153,13 @@ void PianoRoll::wheelEvent(QWheelEvent * we ) NoteVector notes; notes += m_pattern->notes(); + // When alt is pressed we only edit the note under the cursor + bool altPressed = we->modifiers() & Qt::AltModifier; // go through notes to figure out which one we want to change NoteVector nv; foreach( Note * i, notes ) { - if( i->pos().getTicks() >= ticks_start - && i->pos().getTicks() <= ticks_end - && i->length().getTicks() != 0 - && ( i->selected() || ! isSelection() ) ) + if( i->withinRange( ticks_start, ticks_end ) || ( i->selected() && !altPressed ) ) { nv += i; } diff --git a/src/gui/editors/SongEditor.cpp b/src/gui/editors/SongEditor.cpp index a9dab5d83..2807c7a67 100644 --- a/src/gui/editors/SongEditor.cpp +++ b/src/gui/editors/SongEditor.cpp @@ -555,6 +555,7 @@ void SongEditor::updatePosition( const MidiTime & _t ) && m_timeLine->autoScroll() == TimeLineWidget::AutoScrollEnabled) || m_scrollBack == true ) { + m_smoothScroll = ConfigManager::inst()->value( "ui", "smoothscroll" ).toInt(); const int w = width() - widgetWidth - trackOpWidth - contentWidget()->verticalScrollBar()->width(); // width of right scrollbar @@ -579,7 +580,7 @@ void SongEditor::updatePosition( const MidiTime & _t ) if( x >= trackOpWidth + widgetWidth -1 ) { m_positionLine->show(); - m_positionLine->move( x, 50 ); + m_positionLine->move( x, m_timeLine->height() ); } else { diff --git a/src/gui/widgets/FadeButton.cpp b/src/gui/widgets/FadeButton.cpp index 3495ae959..4fea14f97 100644 --- a/src/gui/widgets/FadeButton.cpp +++ b/src/gui/widgets/FadeButton.cpp @@ -55,6 +55,11 @@ FadeButton::~FadeButton() { } +void FadeButton::setActiveColor( const QColor & activated_color ) +{ + m_activatedColor = activated_color; +} + diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 4715fc7d7..d7e53d137 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -36,12 +36,14 @@ #include #include #include +#include #include "FileDialog.h" #include "InstrumentTrack.h" #include "AudioPort.h" #include "AutomationPattern.h" #include "BBTrack.h" +#include "CaptionMenu.h" #include "ConfigManager.h" #include "ControllerConnection.h" #include "debug.h" @@ -927,6 +929,7 @@ InstrumentTrackView::InstrumentTrackView( InstrumentTrack * _it, TrackContainerV connect( m_activityIndicator, SIGNAL( released() ), this, SLOT( activityIndicatorReleased() ) ); _it->setIndicator( m_activityIndicator ); + connect( &_it->m_mutedModel, SIGNAL( dataChanged() ), this, SLOT( muteChanged() ) ); setModel( _it ); } @@ -963,6 +966,30 @@ InstrumentTrackWindow * InstrumentTrackView::topLevelInstrumentTrackWindow() + +/*! \brief Create and assign a new FX Channel for this track */ +void InstrumentTrackView::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 InstrumentTrackView::assignFxLine(int channelIndex) +{ + model()->effectChannelModel()->setValue( channelIndex ); + + gui->fxMixerView()->setCurrentFxLine( channelIndex ); +} + + + // TODO: Add windows to free list on freeInstrumentTrackWindow. // But, don't NULL m_window or disconnect signals. This will allow windows // that are being show/hidden frequently to stay connected. @@ -1131,6 +1158,59 @@ void InstrumentTrackView::midiConfigChanged() +void InstrumentTrackView::muteChanged() +{ + if(model()->m_mutedModel.value() ) + { + m_activityIndicator->setActiveColor( QApplication::palette().color( QPalette::Active, + QPalette::Highlight ) ); + } else + { + m_activityIndicator->setActiveColor( QApplication::palette().color( QPalette::Active, + QPalette::BrightText ) ); + } +} + + + + +QMenu * InstrumentTrackView::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 ); + + QSignalMapper * fxMenuSignalMapper = new QSignalMapper(fxMenu); + + fxMenu->addAction( newFxLabel, this, SLOT( createFxLine() ) ); + fxMenu->addSeparator(); + + for (int i = 0; i < Engine::fxMixer()->fxChannels().size(); ++i) + { + FxChannel * currentChannel = Engine::fxMixer()->fxChannels()[i]; + + if ( currentChannel != fxChannel ) + { + 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); + } + } + + connect(fxMenuSignalMapper, SIGNAL(mapped(int)), this, SLOT(assignFxLine(int))); + + return fxMenu; +} + + class fxLineLcdSpinBox : public LcdSpinBox @@ -1149,6 +1229,30 @@ class fxLineLcdSpinBox : public LcdSpinBox 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() ); + } + }; diff --git a/src/tracks/Pattern.cpp b/src/tracks/Pattern.cpp index c39fbdbcd..e9ba69d9f 100644 --- a/src/tracks/Pattern.cpp +++ b/src/tracks/Pattern.cpp @@ -478,6 +478,29 @@ void Pattern::addSteps() updateBBTrack(); } +void Pattern::cloneSteps() +{ + int oldLength = m_steps; + m_steps += MidiTime::stepsPerTact(); + ensureBeatNotes(); + for(int i = 0; i < MidiTime::stepsPerTact(); ++i ) + { + Note *toCopy = noteAtStep( i ); + if( toCopy ) + { + setStep( oldLength + i, true ); + Note *newNote = noteAtStep( oldLength + i ); + newNote->setKey( toCopy->key() ); + newNote->setLength( toCopy->length() ); + newNote->setPanning( toCopy->getPanning() ); + newNote->setVolume( toCopy->getVolume() ); + } + } + ensureBeatNotes(); + emit dataChanged(); + updateBBTrack(); +} + @@ -776,26 +799,6 @@ void PatternView::constructContextMenu( QMenu * _cm ) -void PatternView::mouseDoubleClickEvent( QMouseEvent * _me ) -{ - if( _me->button() != Qt::LeftButton ) - { - _me->ignore(); - return; - } - if( m_pat->type() == Pattern::MelodyPattern || - !( m_pat->type() == Pattern::BeatPattern && - ( pixelsPerTact() >= 192 || - m_pat->m_steps != MidiTime::stepsPerTact() ) && - _me->y() > height() - s_stepBtnOff->height() ) ) - { - openInPianoRoll(); - } -} - - - - void PatternView::mousePressEvent( QMouseEvent * _me ) { if( _me->button() == Qt::LeftButton && @@ -838,6 +841,7 @@ void PatternView::mousePressEvent( QMouseEvent * _me ) } else // note at step found { + m_pat->addJournalCheckPoint(); if( n->length() < 0 ) { n->setLength( 0 ); // set note as enabled beat note @@ -865,6 +869,19 @@ void PatternView::mousePressEvent( QMouseEvent * _me ) } } +void PatternView::mouseDoubleClickEvent(QMouseEvent *_me) +{ + if( _me->button() != Qt::LeftButton ) + { + _me->ignore(); + return; + } + if( !fixedTCOs() ) + { + openInPianoRoll(); + } +} +