Merge branch 'stable-1.2' into master (@liushuyu)
@@ -2,7 +2,7 @@
|
||||
|
||||
set -e
|
||||
|
||||
PACKAGES="cmake libsndfile-dev fftw3-dev libvorbis-dev libogg-dev
|
||||
PACKAGES="cmake libsndfile-dev fftw3-dev libvorbis-dev libogg-dev libmp3lame-dev
|
||||
libasound2-dev libjack-dev libsdl-dev libsamplerate0-dev libstk0-dev
|
||||
libfluidsynth-dev portaudio19-dev wine-dev g++-multilib libfltk1.3-dev
|
||||
libgig-dev libsoundio-dev"
|
||||
|
||||
@@ -12,7 +12,7 @@ MINGW_PACKAGES="mingw32-x-sdl mingw32-x-libvorbis mingw32-x-fluidsynth mingw32-x
|
||||
mingw32-x-glib2 mingw32-x-portaudio mingw32-x-libsndfile mingw32-x-fftw
|
||||
mingw32-x-flac mingw32-x-fltk mingw32-x-libsamplerate
|
||||
mingw32-x-pkgconfig mingw32-x-binutils mingw32-x-gcc mingw32-x-runtime
|
||||
mingw32-x-libgig mingw32-x-libsoundio $MINGW_PACKAGES"
|
||||
mingw32-x-libgig mingw32-x-libsoundio mingw32-x-lame $MINGW_PACKAGES"
|
||||
|
||||
export MINGW_PACKAGES
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ MINGW_PACKAGES="mingw64-x-sdl mingw64-x-libvorbis mingw64-x-fluidsynth mingw64-x
|
||||
mingw64-x-glib2 mingw64-x-portaudio mingw64-x-libsndfile
|
||||
mingw64-x-fftw mingw64-x-flac mingw64-x-fltk mingw64-x-libsamplerate
|
||||
mingw64-x-pkgconfig mingw64-x-binutils mingw64-x-gcc mingw64-x-runtime
|
||||
mingw64-x-libgig mingw64-x-libsoundio $MINGW_PACKAGES"
|
||||
mingw64-x-libgig mingw64-x-libsoundio mingw64-x-lame $MINGW_PACKAGES"
|
||||
|
||||
export MINGW_PACKAGES
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
set -e
|
||||
|
||||
PACKAGES="cmake pkg-config fftw libogg libvorbis libsndfile libsamplerate jack sdl stk portaudio node fltk"
|
||||
PACKAGES="cmake pkg-config fftw libogg libvorbis lame libsndfile libsamplerate jack sdl libgig libsoundio stk portaudio node fltk"
|
||||
|
||||
if [ "$QT5" ]; then
|
||||
PACKAGES="$PACKAGES qt@5.5"
|
||||
|
||||
@@ -9,6 +9,7 @@ IF(COMMAND CMAKE_POLICY)
|
||||
CMAKE_POLICY(SET CMP0003 NEW)
|
||||
IF (CMAKE_MAJOR_VERSION GREATER 2)
|
||||
CMAKE_POLICY(SET CMP0026 OLD)
|
||||
CMAKE_POLICY(SET CMP0050 OLD)
|
||||
ENDIF()
|
||||
ENDIF(COMMAND CMAKE_POLICY)
|
||||
|
||||
@@ -29,7 +30,7 @@ SET(PROJECT_COPYRIGHT "2008-${PROJECT_YEAR} ${PROJECT_AUTHOR}")
|
||||
SET(VERSION_MAJOR "1")
|
||||
SET(VERSION_MINOR "2")
|
||||
SET(VERSION_RELEASE "0")
|
||||
SET(VERSION_STAGE "rc2")
|
||||
SET(VERSION_STAGE "rc3")
|
||||
SET(VERSION_BUILD "0")
|
||||
SET(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_RELEASE}")
|
||||
IF(VERSION_STAGE)
|
||||
@@ -50,6 +51,7 @@ OPTION(WANT_CAPS "Include C* Audio Plugin Suite (LADSPA plugins)" ON)
|
||||
OPTION(WANT_CARLA "Include Carla plugin" ON)
|
||||
OPTION(WANT_CMT "Include Computer Music Toolkit LADSPA plugins" ON)
|
||||
OPTION(WANT_JACK "Include JACK (Jack Audio Connection Kit) support" ON)
|
||||
OPTION(WANT_MP3LAME "Include MP3/Lame support" ON)
|
||||
OPTION(WANT_OGGVORBIS "Include OGG/Vorbis support" ON)
|
||||
OPTION(WANT_PULSEAUDIO "Include PulseAudio support" ON)
|
||||
OPTION(WANT_PORTAUDIO "Include PortAudio support" ON)
|
||||
@@ -306,6 +308,21 @@ IF(NOT LMMS_HAVE_PULSEAUDIO)
|
||||
ENDIF(NOT LMMS_HAVE_PULSEAUDIO)
|
||||
|
||||
|
||||
# check for MP3/Lame-libraries
|
||||
IF(WANT_MP3LAME)
|
||||
FIND_PACKAGE(Lame)
|
||||
IF(LAME_FOUND)
|
||||
SET(LMMS_HAVE_MP3LAME TRUE)
|
||||
SET(STATUS_MP3LAME "OK")
|
||||
ELSE(LAME_FOUND)
|
||||
SET(STATUS_MP3LAME "not found, please install libmp3lame-dev (or similar)")
|
||||
SET(LAME_LIBRARIES "")
|
||||
SET(LAME_INCLUDE_DIRS "")
|
||||
ENDIF(LAME_FOUND)
|
||||
ELSE(WANT_MP3LAME)
|
||||
SET(STATUS_MP3LAME "Disabled for build")
|
||||
ENDIF(WANT_MP3LAME)
|
||||
|
||||
# check for OGG/Vorbis-libraries
|
||||
IF(WANT_OGGVORBIS)
|
||||
FIND_PACKAGE(OggVorbis)
|
||||
@@ -593,6 +610,7 @@ MESSAGE(
|
||||
"-----------------------------------------\n"
|
||||
"* WAVE : OK\n"
|
||||
"* OGG/VORBIS : ${STATUS_OGGVORBIS}\n"
|
||||
"* MP3/Lame : ${STATUS_MP3LAME}\n"
|
||||
)
|
||||
|
||||
MESSAGE(
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
[](https://travis-ci.org/LMMS/lmms)
|
||||
[](https://lmms.io/download)
|
||||
[](https://github.com/LMMS/lmms/releases)
|
||||
[](https://discord.gg/5kSc32Z)
|
||||
[](https://discord.gg/3sc5su7)
|
||||
[](https://www.transifex.com/lmms/lmms/)
|
||||
|
||||
What is LMMS?
|
||||
|
||||
16
cmake/modules/FindLame.cmake
Normal file
@@ -0,0 +1,16 @@
|
||||
# - Try to find LAME
|
||||
# Once done this will define
|
||||
#
|
||||
# LAME_FOUND - system has liblame
|
||||
# LAME_INCLUDE_DIRS - the liblame include directory
|
||||
# LAME_LIBRARIES - The liblame libraries
|
||||
|
||||
find_path(LAME_INCLUDE_DIRS lame/lame.h)
|
||||
find_library(LAME_LIBRARIES mp3lame)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Lame DEFAULT_MSG LAME_INCLUDE_DIRS LAME_LIBRARIES)
|
||||
|
||||
list(APPEND LAME_DEFINITIONS -DHAVE_LIBMP3LAME=1)
|
||||
|
||||
mark_as_advanced(LAME_INCLUDE_DIRS LAME_LIBRARIES LAME_DEFINITIONS)
|
||||
@@ -7,11 +7,17 @@ SET(CPACK_NSIS_URL_INFO_ABOUT "${PROJECT_URL}" PARENT_SCOPE)
|
||||
SET(CPACK_NSIS_CONTACT "${PROJECT_EMAIL}" PARENT_SCOPE)
|
||||
SET(CPACK_PACKAGE_EXECUTABLES "${CMAKE_PROJECT_NAME}.exe;${PROJECT_NAME_UCASE}" PARENT_SCOPE)
|
||||
SET(CPACK_NSIS_MENU_LINKS "${CMAKE_PROJECT_NAME}.exe;${PROJECT_NAME_UCASE}" PARENT_SCOPE)
|
||||
SET(CPACK_NSIS_DEFINES "!include ${CMAKE_SOURCE_DIR}/cmake/nsis/FileAssociation.nsh")
|
||||
SET(CPACK_NSIS_DEFINES "
|
||||
!include ${CMAKE_SOURCE_DIR}/cmake/nsis/FileAssociation.nsh
|
||||
!include LogicLib.nsh
|
||||
!include WinVer.nsh")
|
||||
SET(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${VERSION}-win32")
|
||||
SET(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "
|
||||
SET(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "
|
||||
\\\${registerExtension} \\\"$INSTDIR\\\\${CMAKE_PROJECT_NAME}.exe\\\" \\\".mmp\\\" \\\"${PROJECT_NAME_UCASE} Project\\\"
|
||||
\\\${registerExtension} \\\"$INSTDIR\\\\${CMAKE_PROJECT_NAME}.exe\\\" \\\".mmpz\\\" \\\"${PROJECT_NAME_UCASE} Project (compressed)\\\"
|
||||
\\\${IfNot} \\\${AtMostWin7}
|
||||
WriteRegDWORD HKLM \\\"Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\SideBySide\\\" \\\"PreferExternalManifest\\\" \\\"1\\\"
|
||||
\\\${EndIf}
|
||||
" PARENT_SCOPE)
|
||||
SET(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS "
|
||||
\\\${unregisterExtension} \\\".mmp\\\" \\\"${PROJECT_NAME_UCASE} Project\\\"
|
||||
@@ -64,3 +70,4 @@ IF(LMMS_HAVE_STK)
|
||||
INSTALL(FILES ${RAWWAVES} DESTINATION "${DATA_DIR}/stk/rawwaves")
|
||||
ENDIF()
|
||||
|
||||
INSTALL(FILES "lmms.exe.manifest" DESTINATION .)
|
||||
|
||||
8
cmake/nsis/lmms.exe.manifest
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
|
||||
<asmv3:application>
|
||||
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
|
||||
<ms_windowsSettings:dpiAware xmlns:ms_windowsSettings="http://schemas.microsoft.com/SMI/2005/WindowsSettings">false</ms_windowsSettings:dpiAware>
|
||||
</asmv3:windowsSettings>
|
||||
</asmv3:application>
|
||||
</assembly>
|
||||
@@ -31,7 +31,7 @@ FOREACH(_ts_file ${lmms_LOCALES})
|
||||
COMMAND "${QT_LUPDATE_EXECUTABLE}" -locations none -no-obsolete -I ${CMAKE_SOURCE_DIR}/include/ ${LMMS_SRCS} ${LMMS_INCLUDES} ${LMMS_UIS} `find "\"${CMAKE_SOURCE_DIR}/plugins/\"" -type f -name '*.cpp' -or -name '*.h'` -ts "\"${_ts_file}\""
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
ADD_CUSTOM_TARGET(${_qm_target}
|
||||
COMMAND "${QT_LRELEASE_EXECUTABLE}" "\"${_ts_file}\"" -qm "\"${_qm_file}\""
|
||||
COMMAND "${QT_LRELEASE_EXECUTABLE}" "${_ts_file}" -qm "${_qm_file}"
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
LIST(APPEND ts_targets "${_ts_target}")
|
||||
LIST(APPEND qm_targets "${_qm_target}")
|
||||
|
||||
@@ -721,10 +721,6 @@ If you're interested in translating LMMS in another language or want to imp
|
||||
<source>Input Gain:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>NOIS</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Input Noise:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
@@ -741,10 +737,6 @@ If you're interested in translating LMMS in another language or want to imp
|
||||
<source>Output Clip:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Rate</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Rate Enabled</source>
|
||||
<translation type="unfinished"></translation>
|
||||
@@ -753,10 +745,6 @@ If you're interested in translating LMMS in another language or want to imp
|
||||
<source>Enable samplerate-crushing</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Depth</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Depth Enabled</source>
|
||||
<translation type="unfinished"></translation>
|
||||
@@ -769,20 +757,28 @@ If you're interested in translating LMMS in another language or want to imp
|
||||
<source>Sample rate:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>STD</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Stereo difference:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Levels</source>
|
||||
<source>Levels:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Levels:</source>
|
||||
<source>NOISE</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>FREQ</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>STEREO</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>QUANT</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
@@ -2170,10 +2166,6 @@ Please make sure you have write permission to the file and the directory contain
|
||||
<source>RATE</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Rate:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>AMNT</source>
|
||||
<translation type="unfinished"></translation>
|
||||
@@ -2194,6 +2186,10 @@ Please make sure you have write permission to the file and the directory contain
|
||||
<source>Invert</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Period:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FxLine</name>
|
||||
@@ -3370,22 +3366,10 @@ You can remove and move FX channels in the context menu, which is accessed by ri
|
||||
<source>FX channel</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>ENV/LFO</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>FUNC</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>FX</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>MIDI</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Save preset</source>
|
||||
<translation type="unfinished"></translation>
|
||||
@@ -3394,10 +3378,6 @@ You can remove and move FX channels in the context menu, which is accessed by ri
|
||||
<source>XML preset file (*.xpf)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>PLUGIN</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Pitch range (semitones)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
@@ -3414,10 +3394,6 @@ You can remove and move FX channels in the context menu, which is accessed by ri
|
||||
<source>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.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>MISC</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Use these controls to view and edit the next/previous track in the song editor.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
@@ -3426,6 +3402,30 @@ You can remove and move FX channels in the context menu, which is accessed by ri
|
||||
<source>SAVE</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Envelope, filter & LFO</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Chord stacking & arpeggio</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Effects</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>MIDI settings</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Miscellaneous</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Plugin</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Knob</name>
|
||||
@@ -3913,14 +3913,6 @@ Please visit http://lmms.sf.net/wiki for documentation on LMMS.</source>
|
||||
<source>Recover the file. Please don't run multiple instances of LMMS when you do this.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Ignore</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Launch LMMS as usual but with automatic backup disabled to prevent the present recover file from being overwritten.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Discard</source>
|
||||
<translation type="unfinished"></translation>
|
||||
@@ -3993,10 +3985,6 @@ Please visit http://lmms.sf.net/wiki for documentation on LMMS.</source>
|
||||
<source>Recover session. Please save your work!</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Automatic backup disabled. Remember to save your work!</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Recovered project not saved</source>
|
||||
<translation type="unfinished"></translation>
|
||||
@@ -5706,14 +5694,6 @@ Reason: "%2"</source>
|
||||
</context>
|
||||
<context>
|
||||
<name>ProjectNotes</name>
|
||||
<message>
|
||||
<source>Project notes</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Put down your project notes here.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Edit Actions</source>
|
||||
<translation type="unfinished"></translation>
|
||||
@@ -5822,6 +5802,14 @@ Reason: "%2"</source>
|
||||
<source>&Color...</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Project Notes</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter project notes here</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>ProjectRenderer</name>
|
||||
|
||||
89
data/projects/templates/default.mpt
Normal file
@@ -0,0 +1,89 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE lmms-project>
|
||||
<lmms-project version="1.0" creator="LMMS" creatorversion="1.2.0" type="song">
|
||||
<head timesig_numerator="4" mastervol="100" timesig_denominator="4" bpm="140" masterpitch="0"/>
|
||||
<song>
|
||||
<trackcontainer width="600" x="5" y="5" maximized="0" height="300" visible="1" type="song" minimized="0">
|
||||
<track muted="0" type="0" name="TripleOscillator" solo="0">
|
||||
<instrumenttrack pan="0" fxch="0" usemasterpitch="1" pitchrange="1" pitch="0" basenote="57" vol="100">
|
||||
<instrument name="tripleoscillator">
|
||||
<tripleoscillator phoffset2="0" userwavefile0="" finer0="0" userwavefile1="" finer1="0" userwavefile2="" finer2="0" coarse0="0" coarse1="-12" coarse2="-24" finel0="0" finel1="0" modalgo1="2" modalgo2="2" finel2="0" pan0="0" modalgo3="2" pan1="0" stphdetun0="0" pan2="0" stphdetun1="0" wavetype0="0" stphdetun2="0" wavetype1="0" wavetype2="0" vol0="33" vol1="33" phoffset0="0" phoffset1="0" vol2="33"/>
|
||||
</instrument>
|
||||
<eldata fres="0.5" ftype="0" fcut="14000" fwet="0">
|
||||
<elvol lspd_denominator="4" sustain="0.5" pdel="0" userwavefile="" dec="0.5" lamt="0" latt="0" rel="0.1" amt="0" x100="0" att="0" lpdel="0" hold="0.5" lspd_syncmode="0" lshp="0" lspd="0.1" ctlenvamt="0" lspd_numerator="4"/>
|
||||
<elcut lspd_denominator="4" sustain="0.5" pdel="0" userwavefile="" dec="0.5" lamt="0" latt="0" rel="0.1" amt="0" x100="0" att="0" lpdel="0" hold="0.5" lspd_syncmode="0" lshp="0" lspd="0.1" ctlenvamt="0" lspd_numerator="4"/>
|
||||
<elres lspd_denominator="4" sustain="0.5" pdel="0" userwavefile="" dec="0.5" lamt="0" latt="0" rel="0.1" amt="0" x100="0" att="0" lpdel="0" hold="0.5" lspd_syncmode="0" lshp="0" lspd="0.1" ctlenvamt="0" lspd_numerator="4"/>
|
||||
</eldata>
|
||||
<chordcreator chord="0" chordrange="1" chord-enabled="0"/>
|
||||
<arpeggiator arptime="100" arprange="1" arpskip="0" arptime_denominator="4" arptime_syncmode="0" arpmode="0" arpcycle="0" arp-enabled="0" arp="0" arptime_numerator="4" arpdir="0" arpmiss="0" arpgate="100"/>
|
||||
<midiport inputcontroller="0" fixedoutputvelocity="-1" inputchannel="0" outputcontroller="0" writable="0" outputchannel="1" fixedinputvelocity="-1" fixedoutputnote="-1" outputprogram="1" basevelocity="63" readable="0"/>
|
||||
<fxchain numofeffects="0" enabled="0"/>
|
||||
</instrumenttrack>
|
||||
</track>
|
||||
<track muted="0" type="2" name="Sample track" solo="0">
|
||||
<sampletrack pan="0" vol="100">
|
||||
<fxchain numofeffects="0" enabled="0"/>
|
||||
</sampletrack>
|
||||
</track>
|
||||
<track muted="0" type="1" name="Beat/Bassline 0" solo="0">
|
||||
<bbtrack>
|
||||
<trackcontainer width="640" x="610" y="5" maximized="0" height="400" visible="0" type="bbtrackcontainer" minimized="0">
|
||||
<track muted="0" type="0" name="Kicker" solo="0">
|
||||
<instrumenttrack pan="0" fxch="0" usemasterpitch="1" pitchrange="1" pitch="0" basenote="57" vol="100">
|
||||
<instrument name="kicker">
|
||||
<kicker decay_numerator="4" decay_denominator="4" distend="0.8" click="0.4" endnote="0" version="1" decay_syncmode="0" decay="440" noise="0" slope="0.06" dist="0.8" env="0.163" startnote="1" startfreq="150" endfreq="40" gain="1"/>
|
||||
</instrument>
|
||||
<eldata fres="0.5" ftype="0" fcut="14000" fwet="0">
|
||||
<elvol lspd_denominator="4" sustain="0.5" pdel="0" userwavefile="" dec="0.5" lamt="0" latt="0" rel="0.1" amt="0" x100="0" att="0" lpdel="0" hold="0.5" lspd_syncmode="0" lshp="0" lspd="0.1" ctlenvamt="0" lspd_numerator="4"/>
|
||||
<elcut lspd_denominator="4" sustain="0.5" pdel="0" userwavefile="" dec="0.5" lamt="0" latt="0" rel="0.1" amt="0" x100="0" att="0" lpdel="0" hold="0.5" lspd_syncmode="0" lshp="0" lspd="0.1" ctlenvamt="0" lspd_numerator="4"/>
|
||||
<elres lspd_denominator="4" sustain="0.5" pdel="0" userwavefile="" dec="0.5" lamt="0" latt="0" rel="0.1" amt="0" x100="0" att="0" lpdel="0" hold="0.5" lspd_syncmode="0" lshp="0" lspd="0.1" ctlenvamt="0" lspd_numerator="4"/>
|
||||
</eldata>
|
||||
<chordcreator chord="0" chordrange="1" chord-enabled="0"/>
|
||||
<arpeggiator arptime="100" arprange="1" arpskip="0" arptime_denominator="4" arptime_syncmode="0" arpmode="0" arpcycle="0" arp-enabled="0" arp="0" arptime_numerator="4" arpdir="0" arpmiss="0" arpgate="100"/>
|
||||
<midiport inputcontroller="0" fixedoutputvelocity="-1" inputchannel="0" outputcontroller="0" writable="0" outputchannel="1" fixedinputvelocity="-1" fixedoutputnote="-1" outputprogram="1" basevelocity="63" readable="0"/>
|
||||
<fxchain numofeffects="0" enabled="0"/>
|
||||
</instrumenttrack>
|
||||
<pattern steps="16" muted="0" type="0" name="Kicker" pos="0"/>
|
||||
</track>
|
||||
</trackcontainer>
|
||||
</bbtrack>
|
||||
</track>
|
||||
<track muted="0" type="5" name="Automation track" solo="0">
|
||||
<automationtrack/>
|
||||
</track>
|
||||
</trackcontainer>
|
||||
<track muted="0" type="6" name="Automation track" solo="0">
|
||||
<automationtrack/>
|
||||
<automationpattern tens="1" mute="0" prog="0" name="Numerator" pos="0" len="192">
|
||||
<object id="4975896"/>
|
||||
</automationpattern>
|
||||
<automationpattern tens="1" mute="0" prog="0" name="Denominator" pos="0" len="192">
|
||||
<object id="6613237"/>
|
||||
</automationpattern>
|
||||
<automationpattern tens="1" mute="0" prog="0" name="Tempo" pos="0" len="192">
|
||||
<object id="6054005"/>
|
||||
</automationpattern>
|
||||
<automationpattern tens="1" mute="0" prog="0" name="Master volume" pos="0" len="192">
|
||||
<object id="1345820"/>
|
||||
</automationpattern>
|
||||
<automationpattern tens="1" mute="0" prog="0" name="Master pitch" pos="0" len="192">
|
||||
<object id="5865711"/>
|
||||
</automationpattern>
|
||||
</track>
|
||||
<fxmixer width="543" x="5" y="310" maximized="0" height="335" visible="1" minimized="0">
|
||||
<fxchannel num="0" muted="0" volume="1" name="Master" soloed="0">
|
||||
<fxchain numofeffects="0" enabled="0"/>
|
||||
</fxchannel>
|
||||
</fxmixer>
|
||||
<ControllerRackView width="350" x="680" y="310" maximized="0" height="200" visible="1" minimized="0"/>
|
||||
<pianoroll width="640" x="5" y="5" maximized="0" height="480" visible="0" minimized="0"/>
|
||||
<automationeditor width="640" x="-36" y="0" maximized="0" height="400" visible="0" minimized="0"/>
|
||||
<projectnotes width="640" x="700" y="10" maximized="0" height="400" visible="0" minimized="0"><![CDATA[<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Noto Sans'; font-size:9pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" color:#e0e0e0;">Enter project notes here</span></p></body></html>]]></projectnotes>
|
||||
<timeline lp1pos="192" lp0pos="0" lpstate="0"/>
|
||||
<controllers/>
|
||||
</song>
|
||||
</lmms-project>
|
||||
@@ -139,6 +139,19 @@ PianoRoll {
|
||||
qproperty-textShadow: rgb( 240, 240, 240 );
|
||||
}
|
||||
|
||||
TabWidget {
|
||||
background-color: #5b6571;
|
||||
qproperty-tabText: rgba(255, 255, 255, 180);
|
||||
qproperty-tabTitleText: #fff;
|
||||
qproperty-tabSelected: #61666b;
|
||||
qproperty-tabBackground: #3c434b;
|
||||
qproperty-tabBorder: #3c434b;
|
||||
}
|
||||
|
||||
GroupBox {
|
||||
background-color: #5b6571;
|
||||
}
|
||||
|
||||
/* main toolbar oscilloscope - can have transparent bg now */
|
||||
|
||||
VisualizationWidget {
|
||||
@@ -281,6 +294,11 @@ TrackContainerView QFrame{
|
||||
background-color: #49515b;
|
||||
}
|
||||
|
||||
/* background for track controls */
|
||||
TrackView > QWidget {
|
||||
background-color: #5b6571;
|
||||
}
|
||||
|
||||
/* autoscroll, loop, stop behaviour toggle buttons */
|
||||
|
||||
/* track background colors */
|
||||
@@ -523,6 +541,12 @@ PluginDescWidget:hover {
|
||||
background-color: #e0e0e0;
|
||||
}
|
||||
|
||||
/* piano widget */
|
||||
|
||||
PianoView {
|
||||
background-color: #14171a;
|
||||
}
|
||||
|
||||
/* font sizes for text buttons */
|
||||
|
||||
FxMixerView QPushButton, EffectRackView QPushButton, ControllerRackView QPushButton {
|
||||
@@ -543,6 +567,7 @@ FxLine {
|
||||
/* persistent peak markers for fx peak meters */
|
||||
Fader {
|
||||
qproperty-peakGreen: rgb( 74, 253, 133);
|
||||
qproperty-peakYellow: rgb(224, 222, 18);
|
||||
qproperty-peakRed: rgb( 255, 100, 100);
|
||||
}
|
||||
|
||||
|
||||
BIN
data/themes/default/env_lfo_tab.png
Normal file
|
After Width: | Height: | Size: 255 B |
BIN
data/themes/default/func_tab.png
Normal file
|
After Width: | Height: | Size: 179 B |
BIN
data/themes/default/fx_tab.png
Normal file
|
After Width: | Height: | Size: 292 B |
BIN
data/themes/default/midi_tab.png
Normal file
|
After Width: | Height: | Size: 170 B |
BIN
data/themes/default/misc_tab.png
Normal file
|
After Width: | Height: | Size: 188 B |
BIN
data/themes/default/plugin_tab.png
Normal file
|
After Width: | Height: | Size: 210 B |
@@ -136,6 +136,19 @@ PianoRoll {
|
||||
qproperty-textShadow: #fff;
|
||||
}
|
||||
|
||||
TabWidget {
|
||||
background-color: #262b30;
|
||||
qproperty-tabText: rgba(255, 255, 255, 180);
|
||||
qproperty-tabTitleText: #fff;
|
||||
qproperty-tabSelected: #323940;
|
||||
qproperty-tabBackground: #181b1f;
|
||||
qproperty-tabBorder: #181b1f;
|
||||
}
|
||||
|
||||
GroupBox {
|
||||
background-color: #262b30;
|
||||
}
|
||||
|
||||
/* main toolbar oscilloscope - can have transparent bg now */
|
||||
|
||||
VisualizationWidget {
|
||||
|
||||
|
Before Width: | Height: | Size: 496 B |
|
Before Width: | Height: | Size: 403 B |
@@ -85,3 +85,7 @@ Chrissy McManus
|
||||
Oskar Wallgren
|
||||
<oskar/dot/wallgren13/at/gmail/dot/com>
|
||||
Development
|
||||
|
||||
Michael Gregorius
|
||||
<michael/dot/gregorius/dot/git/at/arcor/dot/de>
|
||||
Development
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
.\" First parameter, NAME, should be all caps
|
||||
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
||||
.\" other parameters are allowed: see man(7), man(1)
|
||||
.TH LMMS 1 "February 17, 2016"
|
||||
.TH LMMS 1 "June 15, 2017"
|
||||
.\" Please adjust this date whenever revising the manpage.
|
||||
.\"
|
||||
.\" Some roff macros, for reference:
|
||||
@@ -52,6 +52,9 @@ lmms \- software for easy music production
|
||||
.RB "[ \--\fBloop\fP ]"
|
||||
.br
|
||||
.B lmms
|
||||
.RB "[ \--\fBmode\fP \fIstereomode\fP ]"
|
||||
.br
|
||||
.B lmms
|
||||
.RB "[ \--\fBoutput\fP \fIpath\fP ]"
|
||||
.br
|
||||
.B lmms
|
||||
@@ -94,7 +97,7 @@ Get the configuration from \fIconfigfile\fP instead of ~/.lmmsrc.xml (default)
|
||||
.IP "\fB\-d, --dump\fP \fIin\fP
|
||||
Dump XML of compressed file \fIin\fP (i.e. MMPZ-file)
|
||||
.IP "\fB\-f, --format\fP \fIformat\fP
|
||||
Specify format of render-output where \fIformat\fP is either 'wav' or 'ogg'
|
||||
Specify format of render-output where \fIformat\fP is either 'wav', 'ogg' or 'mp3'.
|
||||
.IP "\fB\ --geometry\fP \fIgeometry\fP
|
||||
Specify the prefered size and position of the main window
|
||||
.br
|
||||
@@ -111,6 +114,8 @@ Import MIDI file \fIin\fP
|
||||
If -e is specified lmms exits after importing the file.
|
||||
.IP "\fB\-l, --loop
|
||||
Render the given file as a loop, i.e. stop rendering at exactly the end of the song. Additional silence or reverb tails at the end of the song are not rendered.
|
||||
.IP "\fB\-m, --mode\fP \fIstereomode\fP
|
||||
Set the stereo mode used for the MP3 export. \fIstereomode\fP can be either 's' (stereo mode), 'j' (joint stereo) or 'm' (mono). If no mode is given 'j' is used as the default.
|
||||
.IP "\fB\-o, --output\fP \fIpath\fP
|
||||
Render into \fIpath\fP
|
||||
.br
|
||||
|
||||
74
include/AudioFileMP3.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* AudioFileMP3.h - Audio-device which encodes a wave stream into
|
||||
* an MP3 file. This is used for song export.
|
||||
*
|
||||
* Copyright (c) 2017 to present Michael Gregorius <michael.gregorius.git/at/arcor[dot]de>
|
||||
*
|
||||
* This file is part of LMMS - https://lmms.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_FILE_MP3_H
|
||||
#define AUDIO_FILE_MP3_H
|
||||
|
||||
#include "lmmsconfig.h"
|
||||
|
||||
#ifdef LMMS_HAVE_MP3LAME
|
||||
|
||||
#include "AudioFileDevice.h"
|
||||
|
||||
#include "lame/lame.h"
|
||||
|
||||
|
||||
class AudioFileMP3 : public AudioFileDevice
|
||||
{
|
||||
public:
|
||||
AudioFileMP3( OutputSettings const & outputSettings,
|
||||
const ch_cnt_t _channels,
|
||||
bool & successful,
|
||||
const QString & _file,
|
||||
Mixer* mixer );
|
||||
virtual ~AudioFileMP3();
|
||||
|
||||
static AudioFileDevice * getInst( const QString & outputFilename,
|
||||
OutputSettings const & outputSettings,
|
||||
const ch_cnt_t channels,
|
||||
Mixer* mixer,
|
||||
bool & successful )
|
||||
{
|
||||
return new AudioFileMP3( outputSettings, channels, successful,
|
||||
outputFilename, mixer );
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void writeBuffer( const surroundSampleFrame * /* _buf*/,
|
||||
const fpp_t /*_frames*/,
|
||||
const float /*_master_gain*/ );
|
||||
|
||||
private:
|
||||
void flushRemainingBuffers();
|
||||
bool initEncoder();
|
||||
void tearDownEncoder();
|
||||
|
||||
private:
|
||||
lame_t m_lame;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -407,7 +407,7 @@ public:
|
||||
{
|
||||
}
|
||||
float getRoundedValue() const;
|
||||
float getDigitCount();
|
||||
int getDigitCount() const;
|
||||
defaultTypedMethods(float);
|
||||
|
||||
} ;
|
||||
|
||||
@@ -217,6 +217,9 @@ public:
|
||||
|
||||
const QString & value( const QString & cls,
|
||||
const QString & attribute ) const;
|
||||
const QString & value( const QString & cls,
|
||||
const QString & attribute,
|
||||
const QString & defaultVal ) const;
|
||||
void setValue( const QString & cls, const QString & attribute,
|
||||
const QString & value );
|
||||
void deleteValue( const QString & cls, const QString & attribute);
|
||||
|
||||
@@ -57,7 +57,7 @@ public:
|
||||
|
||||
protected:
|
||||
virtual void mousePressEvent( QMouseEvent * _me );
|
||||
virtual void resizeEvent( QResizeEvent * _re );
|
||||
virtual void paintEvent( QPaintEvent * _pe );
|
||||
|
||||
|
||||
private:
|
||||
|
||||
@@ -110,8 +110,7 @@ public:
|
||||
enum SessionState
|
||||
{
|
||||
Normal,
|
||||
Recover,
|
||||
Limited,
|
||||
Recover
|
||||
};
|
||||
|
||||
void setSession( SessionState session )
|
||||
@@ -143,7 +142,7 @@ public:
|
||||
return m_keyMods.m_alt;
|
||||
}
|
||||
|
||||
static void saveWidgetState( QWidget * _w, QDomElement & _de, QSize const & sizeIfInvisible = QSize(0, 0) );
|
||||
static void saveWidgetState( QWidget * _w, QDomElement & _de );
|
||||
static void restoreWidgetState( QWidget * _w, const QDomElement & _de );
|
||||
|
||||
public slots:
|
||||
|
||||
@@ -38,6 +38,13 @@ public:
|
||||
NumDepths
|
||||
};
|
||||
|
||||
enum StereoMode
|
||||
{
|
||||
StereoMode_Stereo,
|
||||
StereoMode_JointStereo,
|
||||
StereoMode_Mono
|
||||
};
|
||||
|
||||
class BitRateSettings
|
||||
{
|
||||
public:
|
||||
@@ -60,10 +67,19 @@ public:
|
||||
public:
|
||||
OutputSettings( sample_rate_t sampleRate,
|
||||
BitRateSettings const & bitRateSettings,
|
||||
BitDepth bitDepth ) :
|
||||
BitDepth bitDepth,
|
||||
StereoMode stereoMode ) :
|
||||
m_sampleRate(sampleRate),
|
||||
m_bitRateSettings(bitRateSettings),
|
||||
m_bitDepth(bitDepth)
|
||||
m_bitDepth(bitDepth),
|
||||
m_stereoMode(stereoMode)
|
||||
{
|
||||
}
|
||||
|
||||
OutputSettings( sample_rate_t sampleRate,
|
||||
BitRateSettings const & bitRateSettings,
|
||||
BitDepth bitDepth ) :
|
||||
OutputSettings(sampleRate, bitRateSettings, bitDepth, StereoMode_Stereo )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -76,10 +92,14 @@ public:
|
||||
BitDepth getBitDepth() const { return m_bitDepth; }
|
||||
void setBitDepth(BitDepth bitDepth) { m_bitDepth = bitDepth; }
|
||||
|
||||
StereoMode getStereoMode() const { return m_stereoMode; }
|
||||
void setStereoMode(StereoMode stereoMode) { m_stereoMode = stereoMode; }
|
||||
|
||||
private:
|
||||
sample_rate_t m_sampleRate;
|
||||
BitRateSettings m_bitRateSettings;
|
||||
BitDepth m_bitDepth;
|
||||
StereoMode m_stereoMode;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -88,7 +88,7 @@ public:
|
||||
{
|
||||
return m_patternType;
|
||||
}
|
||||
void checkType();
|
||||
|
||||
|
||||
// next/previous track based on position in the containing track
|
||||
Pattern * previousPattern() const;
|
||||
@@ -132,6 +132,7 @@ private:
|
||||
MidiTime beatPatternLength() const;
|
||||
|
||||
void setType( PatternTypes _new_pattern_type );
|
||||
void checkType();
|
||||
|
||||
void resizeToFirstTrack();
|
||||
|
||||
|
||||
@@ -39,11 +39,14 @@ public:
|
||||
{
|
||||
WaveFile,
|
||||
OggFile,
|
||||
MP3File,
|
||||
NumFileFormats
|
||||
} ;
|
||||
|
||||
struct FileEncodeDevice
|
||||
{
|
||||
bool isAvailable() const { return m_getDevInst != nullptr; }
|
||||
|
||||
ExportFileFormats m_fileFormat;
|
||||
const char * m_description;
|
||||
const char * m_extension;
|
||||
|
||||
@@ -153,6 +153,7 @@ public:
|
||||
|
||||
public slots:
|
||||
void updateTcos();
|
||||
void setPlayingTcos( bool isPlaying );
|
||||
|
||||
private:
|
||||
FloatModel m_volumeModel;
|
||||
|
||||
@@ -97,6 +97,10 @@ public:
|
||||
|
||||
void processNextBuffer();
|
||||
|
||||
inline int getLoadingTrackCount() const
|
||||
{
|
||||
return m_nLoadingTrack;
|
||||
}
|
||||
inline int getMilliseconds() const
|
||||
{
|
||||
return m_elapsedMilliSeconds;
|
||||
@@ -339,6 +343,7 @@ private:
|
||||
|
||||
ControllerVector m_controllers;
|
||||
|
||||
int m_nLoadingTrack;
|
||||
|
||||
QString m_fileName;
|
||||
QString m_oldFileName;
|
||||
|
||||
@@ -81,6 +81,7 @@ public slots:
|
||||
void setEditModeSelect();
|
||||
|
||||
void updatePosition( const MidiTime & t );
|
||||
void updatePositionLine();
|
||||
|
||||
protected:
|
||||
virtual void closeEvent( QCloseEvent * ce );
|
||||
@@ -152,6 +153,9 @@ public:
|
||||
|
||||
SongEditor* m_editor;
|
||||
|
||||
protected:
|
||||
virtual void resizeEvent( QResizeEvent * event );
|
||||
|
||||
protected slots:
|
||||
void play();
|
||||
void record();
|
||||
@@ -162,6 +166,7 @@ protected slots:
|
||||
|
||||
signals:
|
||||
void playTriggered();
|
||||
void resized();
|
||||
|
||||
private:
|
||||
QAction* m_addBBTrackAction;
|
||||
|
||||
@@ -29,25 +29,47 @@
|
||||
#include <QWidget>
|
||||
#include <QtCore/QMap>
|
||||
|
||||
const int TEXT_TAB_HEIGHT = 14;
|
||||
const int GRAPHIC_TAB_HEIGHT = 17;
|
||||
|
||||
class TabWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TabWidget( const QString & _caption, QWidget * _parent );
|
||||
TabWidget( const QString & _caption, QWidget * _parent, bool usePixmap = false );
|
||||
virtual ~TabWidget();
|
||||
|
||||
void addTab( QWidget * _w, const QString & _name, int _idx = -1 );
|
||||
void addTab( QWidget * w, const QString & name, const char *pixmap = NULL, int idx = -1 );
|
||||
|
||||
void setActiveTab( int _idx );
|
||||
void setActiveTab( int idx );
|
||||
|
||||
int findTabAtPos( const QPoint *pos );
|
||||
|
||||
inline int activeTab() const
|
||||
{
|
||||
return( m_activeTab );
|
||||
}
|
||||
|
||||
// Themeability
|
||||
Q_PROPERTY( QColor tabText READ tabText WRITE setTabText)
|
||||
Q_PROPERTY( QColor tabTitleText READ tabTitleText WRITE setTabTitleText)
|
||||
Q_PROPERTY( QColor tabSelected READ tabSelected WRITE setTabSelected)
|
||||
Q_PROPERTY( QColor tabBackground READ tabBackground WRITE setTabBackground)
|
||||
Q_PROPERTY( QColor tabBorder READ tabBorder WRITE setTabBorder)
|
||||
|
||||
QColor tabText() const;
|
||||
void setTabText( const QColor & c );
|
||||
QColor tabTitleText() const;
|
||||
void setTabTitleText( const QColor & c );
|
||||
QColor tabSelected() const;
|
||||
void setTabSelected( const QColor & c );
|
||||
QColor tabBackground() const;
|
||||
void setTabBackground( const QColor & c );
|
||||
QColor tabBorder() const;
|
||||
void setTabBorder( const QColor & c );
|
||||
|
||||
protected:
|
||||
virtual bool event( QEvent * event );
|
||||
virtual void mousePressEvent( QMouseEvent * _me );
|
||||
virtual void paintEvent( QPaintEvent * _pe );
|
||||
virtual void resizeEvent( QResizeEvent * _re );
|
||||
@@ -57,16 +79,26 @@ protected:
|
||||
private:
|
||||
struct widgetDesc
|
||||
{
|
||||
QWidget * w; // ptr to widget
|
||||
QString name; // name for widget
|
||||
int nwidth; // width of name when painting
|
||||
QWidget * w; // ptr to widget
|
||||
const char * pixmap; // artwork for the widget
|
||||
QString name; // name for widget
|
||||
int nwidth; // width of name when painting (only valid for text tab)
|
||||
} ;
|
||||
typedef QMap<int, widgetDesc> widgetStack;
|
||||
|
||||
widgetStack m_widgets;
|
||||
int m_activeTab;
|
||||
QString m_caption;
|
||||
quint8 m_tabheight;
|
||||
|
||||
int m_activeTab;
|
||||
QString m_caption; // Tab caption, used as the tooltip text on icon tabs
|
||||
quint8 m_tabbarHeight; // The height of the tab bar
|
||||
quint8 m_tabheight; // The height of the tabs
|
||||
bool m_usePixmap; // true if the tabs are to be displayed with icons. False for text tabs.
|
||||
|
||||
QColor m_tabText; // The color of the tabs' text.
|
||||
QColor m_tabTitleText; // The color of the TabWidget's title text.
|
||||
QColor m_tabSelected; // The highlighting color for the selected tab.
|
||||
QColor m_tabBackground; // The TabWidget's background color.
|
||||
QColor m_tabBorder; // The TabWidget's borders color.
|
||||
} ;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -29,9 +29,10 @@
|
||||
#include <QToolButton>
|
||||
#include <QLineEdit>
|
||||
|
||||
|
||||
class TrackView;
|
||||
|
||||
class TrackRenameLineEdit;
|
||||
|
||||
|
||||
class TrackLabelButton : public QToolButton
|
||||
{
|
||||
@@ -60,7 +61,7 @@ protected:
|
||||
private:
|
||||
TrackView * m_trackView;
|
||||
QString m_iconName;
|
||||
QLineEdit * m_renameLineEdit;
|
||||
TrackRenameLineEdit * m_renameLineEdit;
|
||||
QRect m_buttonRect;
|
||||
QString elideName( const QString &name );
|
||||
|
||||
|
||||
46
include/TrackRenameLineEdit.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* TrackRenameLineEdit.h - class TrackRenameLineEdit
|
||||
*
|
||||
* Copyright (c) 2004-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2017 Alexandre Almeida <http://m374lx.users.sourceforge.net/>
|
||||
*
|
||||
* This file is part of LMMS - https://lmms.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef TRACK_RENAME_LINE_EDIT_H
|
||||
#define TRACK_RENAME_LINE_EDIT_H
|
||||
|
||||
#include <QLineEdit>
|
||||
|
||||
class TrackRenameLineEdit : public QLineEdit
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TrackRenameLineEdit( QWidget * parent );
|
||||
void show();
|
||||
|
||||
protected:
|
||||
virtual void keyPressEvent( QKeyEvent * ke );
|
||||
|
||||
private:
|
||||
QString m_oldName;
|
||||
} ;
|
||||
|
||||
#endif
|
||||
36
plugins/Bitcrush/BitcrushControlDialog.cpp
Normal file → Executable file
@@ -41,73 +41,73 @@ BitcrushControlDialog::BitcrushControlDialog( BitcrushControls * controls ) :
|
||||
QPalette pal;
|
||||
pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap( "artwork" ) );
|
||||
setPalette( pal );
|
||||
setFixedSize( 215, 120 );
|
||||
setFixedSize( 181, 128 );
|
||||
|
||||
// labels
|
||||
QLabel * inLabel = new QLabel( tr( "IN" ), this );
|
||||
inLabel->move( 12, 10);
|
||||
inLabel->move( 24, 15 );
|
||||
|
||||
QLabel * outLabel = new QLabel( tr( "OUT" ), this );
|
||||
outLabel->move( 176, 10 );
|
||||
outLabel->move( 139, 15 );
|
||||
|
||||
// input knobs
|
||||
Knob * inGain = new Knob( knobBright_26, this );
|
||||
inGain->move( 12, 25 );
|
||||
inGain->move( 16, 32 );
|
||||
inGain->setModel( & controls->m_inGain );
|
||||
inGain->setLabel( tr( "GAIN" ) );
|
||||
inGain->setHintText( tr( "Input Gain:" ) + " ", " dBFS" );
|
||||
|
||||
Knob * inNoise = new Knob( knobBright_26, this );
|
||||
inNoise->move( 12, 70 );
|
||||
inNoise->move( 14, 76 );
|
||||
inNoise->setModel( & controls->m_inNoise );
|
||||
inNoise->setLabel( tr( "NOIS" ) );
|
||||
inNoise->setLabel( tr( "NOISE" ) );
|
||||
inNoise->setHintText( tr( "Input Noise:" ) + " ", "%" );
|
||||
|
||||
|
||||
// output knobs
|
||||
Knob * outGain = new Knob( knobBright_26, this );
|
||||
outGain->move( 176, 25 );
|
||||
outGain->move( 138, 32 );
|
||||
outGain->setModel( & controls->m_outGain );
|
||||
outGain->setLabel( tr( "GAIN" ) );
|
||||
outGain->setHintText( tr( "Output Gain:" ) + " ", " dBFS" );
|
||||
|
||||
Knob * outClip = new Knob( knobBright_26, this );
|
||||
outClip->move( 176, 70 );
|
||||
outClip->move( 138, 76 );
|
||||
outClip->setModel( & controls->m_outClip );
|
||||
outClip->setLabel( tr( "CLIP" ) );
|
||||
outClip->setHintText( tr( "Output Clip:" ) + " ", "%" );
|
||||
|
||||
|
||||
// leds
|
||||
LedCheckBox * rateEnabled = new LedCheckBox( tr( "Rate" ), this, tr( "Rate Enabled" ), LedCheckBox::Green );
|
||||
rateEnabled->move( 50, 30 );
|
||||
LedCheckBox * rateEnabled = new LedCheckBox( "", this, tr( "Rate Enabled" ), LedCheckBox::Green );
|
||||
rateEnabled->move( 64, 14 );
|
||||
rateEnabled->setModel( & controls->m_rateEnabled );
|
||||
ToolTip::add( rateEnabled, tr( "Enable samplerate-crushing" ) );
|
||||
|
||||
LedCheckBox * depthEnabled = new LedCheckBox( tr( "Depth" ), this, tr( "Depth Enabled" ), LedCheckBox::Green );
|
||||
depthEnabled->move( 50, 80 );
|
||||
LedCheckBox * depthEnabled = new LedCheckBox( "", this, tr( "Depth Enabled" ), LedCheckBox::Green );
|
||||
depthEnabled->move( 101, 14 );
|
||||
depthEnabled->setModel( & controls->m_depthEnabled );
|
||||
ToolTip::add( depthEnabled, tr( "Enable bitdepth-crushing" ) );
|
||||
|
||||
|
||||
// rate crushing knobs
|
||||
Knob * rate = new Knob( knobBright_26, this );
|
||||
rate->move( 100, 20 );
|
||||
rate->move( 59, 32 );
|
||||
rate->setModel( & controls->m_rate );
|
||||
rate->setLabel( tr( "Rate" ) );
|
||||
rate->setLabel( tr( "FREQ" ) );
|
||||
rate->setHintText( tr( "Sample rate:" ) + " ", " Hz" );
|
||||
|
||||
Knob * stereoDiff = new Knob( knobBright_26, this );
|
||||
stereoDiff->move( 140, 20 );
|
||||
stereoDiff->move( 72, 76 );
|
||||
stereoDiff->setModel( & controls->m_stereoDiff );
|
||||
stereoDiff->setLabel( tr( "STD" ) );
|
||||
stereoDiff->setLabel( tr( "STEREO" ) );
|
||||
stereoDiff->setHintText( tr( "Stereo difference:" ) + " ", "%" );
|
||||
|
||||
|
||||
// depth crushing knob
|
||||
Knob * levels = new Knob( knobBright_26, this );
|
||||
levels->move( 140, 70 );
|
||||
levels->move( 92, 32 );
|
||||
levels->setModel( & controls->m_levels );
|
||||
levels->setLabel( tr( "Levels" ) );
|
||||
levels->setLabel( tr( "QUANT" ) );
|
||||
levels->setHintText( tr( "Levels:" ) + " ", "" );
|
||||
}
|
||||
|
||||
BIN
plugins/Bitcrush/artwork.png
Normal file → Executable file
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 1.3 KiB |
@@ -32,7 +32,7 @@
|
||||
DelayControls::DelayControls( DelayEffect* effect ):
|
||||
EffectControls( effect ),
|
||||
m_effect ( effect ),
|
||||
m_delayTimeModel( 0.5, 0.01, 5.0, 0.0001, 20000.0, this, tr( "Delay Samples" )) ,
|
||||
m_delayTimeModel( 0.5, 0.01, 5.0, 0.0001, 5000.0, this, tr( "Delay Samples" )) ,
|
||||
m_feedbackModel(0.0f,0.0f,1.0f,0.01f,this,tr( "Feedback" ) ),
|
||||
m_lfoTimeModel(2.0, 0.01, 5.0, 0.0001, 20000.0, this, tr( "Lfo Frequency" ) ),
|
||||
m_lfoAmountModel(0.0, 0.0, 0.5, 0.0001, 2000.0, this, tr ( "Lfo Amount" ) ),
|
||||
|
||||
@@ -36,7 +36,7 @@ StereoDelay::StereoDelay( int maxTime, int sampleRate )
|
||||
m_maxLength = maxTime * sampleRate;
|
||||
m_length = m_maxLength;
|
||||
|
||||
m_index = 0;
|
||||
m_writeIndex = 0;
|
||||
m_feedback = 0.0f;
|
||||
setSampleRate( sampleRate );
|
||||
}
|
||||
@@ -57,13 +57,13 @@ StereoDelay::~StereoDelay()
|
||||
|
||||
void StereoDelay::tick( sampleFrame frame )
|
||||
{
|
||||
m_index = ( int )m_length > 0
|
||||
? ( m_index + 1 ) % ( int ) m_length
|
||||
: m_index;
|
||||
float lOut = m_buffer[ m_index ][ 0 ];
|
||||
float rOut = m_buffer[ m_index ] [1 ];
|
||||
m_buffer[ m_index ][ 0 ] = frame[ 0 ] + ( lOut * m_feedback );
|
||||
m_buffer[ m_index ][ 1 ] = frame[ 1 ] + ( rOut * m_feedback );
|
||||
m_writeIndex = ( m_writeIndex + 1 ) % ( int )m_maxLength;
|
||||
int readIndex = m_writeIndex - m_length;
|
||||
if (readIndex < 0 ) { readIndex += m_maxLength; }
|
||||
float lOut = m_buffer[ readIndex ][ 0 ];
|
||||
float rOut = m_buffer[ readIndex ] [1 ];
|
||||
m_buffer[ m_writeIndex ][ 0 ] = frame[ 0 ] + ( lOut * m_feedback );
|
||||
m_buffer[ m_writeIndex ][ 1 ] = frame[ 1 ] + ( rOut * m_feedback );
|
||||
frame[ 0 ] = lOut;
|
||||
frame[ 1 ] = rOut;
|
||||
}
|
||||
@@ -71,6 +71,8 @@ void StereoDelay::tick( sampleFrame frame )
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void StereoDelay::setSampleRate( int sampleRate )
|
||||
{
|
||||
if( m_buffer )
|
||||
|
||||
@@ -52,7 +52,7 @@ private:
|
||||
sampleFrame* m_buffer;
|
||||
int m_maxLength;
|
||||
float m_length;
|
||||
int m_index;
|
||||
int m_writeIndex;
|
||||
float m_feedback;
|
||||
float m_maxTime;
|
||||
};
|
||||
|
||||
24
plugins/DualFilter/DualFilterControlDialog.cpp
Normal file → Executable file
@@ -49,15 +49,15 @@ DualFilterControlDialog::DualFilterControlDialog( DualFilterControls* controls )
|
||||
QPalette pal;
|
||||
pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap( "artwork" ) );
|
||||
setPalette( pal );
|
||||
setFixedSize( 150, 220 );
|
||||
setFixedSize( 373, 109 );
|
||||
|
||||
makeknob( cut1Knob, 33, 30, m_cut1Model, tr( "FREQ" ), tr( "Cutoff frequency" ), "Hz" )
|
||||
makeknob( res1Knob, 75, 30, m_res1Model, tr( "RESO" ), tr( "Resonance" ), "" )
|
||||
makeknob( gain1Knob, 117, 30, m_gain1Model, tr( "GAIN" ), tr( "Gain" ), "%" )
|
||||
makeknob( mixKnob, 62, 100, m_mixModel, tr( "MIX" ), tr( "Mix" ), "" )
|
||||
makeknob( cut2Knob, 33, 145, m_cut2Model, tr( "FREQ" ), tr( "Cutoff frequency" ), "Hz" )
|
||||
makeknob( res2Knob, 75, 145, m_res2Model, tr( "RESO" ), tr( "Resonance" ), "" )
|
||||
makeknob( gain2Knob, 117, 145, m_gain2Model, tr( "GAIN" ), tr( "Gain" ), "%" )
|
||||
makeknob( cut1Knob, 24, 26, m_cut1Model, tr( "FREQ" ), tr( "Cutoff frequency" ), "Hz" )
|
||||
makeknob( res1Knob, 74, 26, m_res1Model, tr( "RESO" ), tr( "Resonance" ), "" )
|
||||
makeknob( gain1Knob, 124, 26, m_gain1Model, tr( "GAIN" ), tr( "Gain" ), "%" )
|
||||
makeknob( mixKnob, 173, 37, m_mixModel, tr( "MIX" ), tr( "Mix" ), "" )
|
||||
makeknob( cut2Knob, 222, 26, m_cut2Model, tr( "FREQ" ), tr( "Cutoff frequency" ), "Hz" )
|
||||
makeknob( res2Knob, 272, 26, m_res2Model, tr( "RESO" ), tr( "Resonance" ), "" )
|
||||
makeknob( gain2Knob, 322, 26, m_gain2Model, tr( "GAIN" ), tr( "Gain" ), "%" )
|
||||
|
||||
gain1Knob-> setVolumeKnob( true );
|
||||
gain2Knob-> setVolumeKnob( true );
|
||||
@@ -67,20 +67,20 @@ DualFilterControlDialog::DualFilterControlDialog( DualFilterControls* controls )
|
||||
LedCheckBox * enabled2Toggle = new LedCheckBox( "", this,
|
||||
tr( "Filter 2 enabled" ), LedCheckBox::Green );
|
||||
|
||||
enabled1Toggle -> move( 5, 30 );
|
||||
enabled1Toggle -> move( 12, 11 );
|
||||
enabled1Toggle -> setModel( &controls -> m_enabled1Model );
|
||||
ToolTip::add( enabled1Toggle, tr( "Click to enable/disable Filter 1" ) );
|
||||
enabled2Toggle -> move( 5, 145 );
|
||||
enabled2Toggle -> move( 210, 11 );
|
||||
enabled2Toggle -> setModel( &controls -> m_enabled2Model );
|
||||
ToolTip::add( enabled2Toggle, tr( "Click to enable/disable Filter 2" ) );
|
||||
|
||||
ComboBox * m_filter1ComboBox = new ComboBox( this );
|
||||
m_filter1ComboBox->setGeometry( 5, 70, 140, 22 );
|
||||
m_filter1ComboBox->setGeometry( 19, 70, 137, 22 );
|
||||
m_filter1ComboBox->setFont( pointSize<8>( m_filter1ComboBox->font() ) );
|
||||
m_filter1ComboBox->setModel( &controls->m_filter1Model );
|
||||
|
||||
ComboBox * m_filter2ComboBox = new ComboBox( this );
|
||||
m_filter2ComboBox->setGeometry( 5, 185, 140, 22 );
|
||||
m_filter2ComboBox->setGeometry( 217, 70, 137, 22 );
|
||||
m_filter2ComboBox->setFont( pointSize<8>( m_filter2ComboBox->font() ) );
|
||||
m_filter2ComboBox->setModel( &controls->m_filter2Model );
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 934 B |
@@ -70,6 +70,10 @@ EqEffect::~EqEffect()
|
||||
|
||||
bool EqEffect::processAudioBuffer( sampleFrame *buf, const fpp_t frames )
|
||||
{
|
||||
//wet/dry controls
|
||||
const float dry = dryLevel();
|
||||
const float wet = wetLevel();
|
||||
sample_t dryS[2];
|
||||
// setup sample exact controls
|
||||
float hpRes = m_eqControls.m_hpResModel.value();
|
||||
float lowShelfRes = m_eqControls.m_lowShelfResModel.value();
|
||||
@@ -205,6 +209,9 @@ bool EqEffect::processAudioBuffer( sampleFrame *buf, const fpp_t frames )
|
||||
|
||||
for( fpp_t f = 0; f < frames; f++)
|
||||
{
|
||||
//wet dry buffer
|
||||
dryS[0] = buf[f][0];
|
||||
dryS[1] = buf[f][1];
|
||||
if( hpActive )
|
||||
{
|
||||
m_hp12.setParameters( sampleRate, *hpFreqPtr, *hpResPtr, 1 );
|
||||
@@ -296,6 +303,10 @@ bool EqEffect::processAudioBuffer( sampleFrame *buf, const fpp_t frames )
|
||||
}
|
||||
}
|
||||
|
||||
//apply wet / dry levels
|
||||
buf[f][1] = ( dry * dryS[1] ) + ( wet * buf[f][1] );
|
||||
buf[f][0] = ( dry * dryS[0] ) + ( wet * buf[f][0] );
|
||||
|
||||
//increment pointers if needed
|
||||
hpResPtr += hpResInc;
|
||||
lowShelfResPtr += lowShelfResInc;
|
||||
|
||||
@@ -35,7 +35,7 @@ FlangerControls::FlangerControls( FlangerEffect *effect ) :
|
||||
EffectControls ( effect ),
|
||||
m_effect ( effect ),
|
||||
m_delayTimeModel(0.001, 0.0001, 0.050, 0.0001, this, tr( "Delay Samples" ) ) ,
|
||||
m_lfoFrequencyModel( 0.25, 0.01, 5, 0.0001, 20000.0 ,this, tr( "Lfo Frequency" ) ),
|
||||
m_lfoFrequencyModel( 0.25, 0.01, 60, 0.0001, 60000.0 ,this, tr( "Lfo Frequency" ) ),
|
||||
m_lfoAmountModel( 0.0, 0.0, 0.0025 , 0.0001 , this , tr( "Seconds" ) ),
|
||||
m_feedbackModel( 0.0 , 0.0 , 1.0 , 0.0001, this, tr( "Regen" ) ),
|
||||
m_whiteNoiseAmountModel( 0.0 , 0.0 , 0.05 , 0.0001, this, tr( "Noise" ) ),
|
||||
|
||||
@@ -52,7 +52,7 @@ FlangerControlsDialog::FlangerControlsDialog( FlangerControls *controls ) :
|
||||
lfoFreqKnob->setVolumeKnob( false );
|
||||
lfoFreqKnob->setModel( &controls->m_lfoFrequencyModel );
|
||||
lfoFreqKnob->setLabel( tr( "RATE" ) );
|
||||
lfoFreqKnob->setHintText( tr ( "Rate:" ) , "Hz" );
|
||||
lfoFreqKnob->setHintText( tr ( "Period:" ) , " Sec" );
|
||||
|
||||
Knob * lfoAmtKnob = new Knob( knobBright_26, this );
|
||||
lfoAmtKnob->move( 85,10 );
|
||||
|
||||
@@ -94,7 +94,7 @@ bool FlangerEffect::processAudioBuffer( sampleFrame *buf, const fpp_t frames )
|
||||
const float noise = m_flangerControls.m_whiteNoiseAmountModel.value();
|
||||
float amplitude = m_flangerControls.m_lfoAmountModel.value() * Engine::mixer()->processingSampleRate();
|
||||
bool invertFeedback = m_flangerControls.m_invertFeedbackModel.value();
|
||||
m_lfo->setFrequency( m_flangerControls.m_lfoFrequencyModel.value() );
|
||||
m_lfo->setFrequency( 1.0/m_flangerControls.m_lfoFrequencyModel.value() );
|
||||
m_lDelay->setFeedback( m_flangerControls.m_feedbackModel.value() );
|
||||
m_rDelay->setFeedback( m_flangerControls.m_feedbackModel.value() );
|
||||
sample_t dryS[2];
|
||||
@@ -107,8 +107,8 @@ bool FlangerEffect::processAudioBuffer( sampleFrame *buf, const fpp_t frames )
|
||||
dryS[0] = buf[f][0];
|
||||
dryS[1] = buf[f][1];
|
||||
m_lfo->tick(&leftLfo, &rightLfo);
|
||||
m_lDelay->setLength( ( float )length + ( amplitude * leftLfo ) );
|
||||
m_rDelay->setLength( ( float )length+ ( amplitude * rightLfo ) );
|
||||
m_lDelay->setLength( ( float )length + amplitude * (leftLfo+1.0) );
|
||||
m_rDelay->setLength( ( float )length + amplitude * (rightLfo+1.0) );
|
||||
if(invertFeedback)
|
||||
{
|
||||
m_lDelay->tick( &buf[f][1] );
|
||||
|
||||
@@ -34,7 +34,7 @@ MonoDelay::MonoDelay( int maxTime , int sampleRate )
|
||||
m_maxLength = maxTime * sampleRate;
|
||||
m_length = m_maxLength;
|
||||
|
||||
m_index = 0;
|
||||
m_writeIndex = 0;
|
||||
m_feedback = 0.0f;
|
||||
setSampleRate( sampleRate );
|
||||
}
|
||||
@@ -54,11 +54,11 @@ MonoDelay::~MonoDelay()
|
||||
|
||||
void MonoDelay::tick( sample_t* sample )
|
||||
{
|
||||
m_index = ( int )m_length > 0
|
||||
? ( m_index + 1 ) % ( int )m_length
|
||||
: m_index;
|
||||
float out = m_buffer[ m_index ];
|
||||
m_buffer[ m_index ] = *sample + ( out * m_feedback );
|
||||
m_writeIndex = ( m_writeIndex + 1 ) % ( int )m_maxLength;
|
||||
int readIndex = m_writeIndex - m_length;
|
||||
if (readIndex < 0 ) { readIndex += m_maxLength; }
|
||||
float out = m_buffer[ readIndex ];
|
||||
m_buffer[ m_writeIndex ] = *sample + ( out * m_feedback );
|
||||
*sample = out;
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ private:
|
||||
sample_t* m_buffer;
|
||||
int m_maxLength;
|
||||
float m_length;
|
||||
int m_index;
|
||||
int m_writeIndex;
|
||||
float m_feedback;
|
||||
float m_maxTime;
|
||||
};
|
||||
|
||||
@@ -2,6 +2,11 @@ if(LMMS_HAVE_GIG)
|
||||
INCLUDE(BuildPlugin)
|
||||
INCLUDE_DIRECTORIES(${GIG_INCLUDE_DIRS})
|
||||
|
||||
# Disable C++11 on Clang until gig.h is patched
|
||||
IF(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
REMOVE_DEFINITIONS(-std=c++0x)
|
||||
ENDIF()
|
||||
|
||||
# Required for not crashing loading files with libgig
|
||||
SET(GCC_COVERAGE_COMPILE_FLAGS "-fexceptions")
|
||||
add_definitions(${GCC_COVERAGE_COMPILE_FLAGS})
|
||||
|
||||
@@ -1066,7 +1066,6 @@ void GigInstrumentView::showFileDialog()
|
||||
types << tr( "GIG Files (*.gig)" );
|
||||
ofd.setNameFilters( types );
|
||||
|
||||
QString dir;
|
||||
if( k->m_filename != "" )
|
||||
{
|
||||
QString f = SampleBuffer::tryToMakeAbsolute( k->m_filename );
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
#include "LcdSpinBox.h"
|
||||
#include "GigPlayer.h"
|
||||
|
||||
#include <fluidsynth.h>
|
||||
#include <QWidget>
|
||||
#include <QLabel>
|
||||
|
||||
|
||||
@@ -7,18 +7,18 @@ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
|
||||
|
||||
BUILD_PLUGIN(
|
||||
reverbsc
|
||||
ReverbSC.cpp
|
||||
ReverbSCControls.cpp
|
||||
ReverbSCControlDialog.cpp
|
||||
ReverbSC.cpp
|
||||
ReverbSCControls.cpp
|
||||
ReverbSCControlDialog.cpp
|
||||
base.c
|
||||
revsc.c
|
||||
dcblock.c
|
||||
MOCFILES
|
||||
ReverbSC.h
|
||||
ReverbSCControls.h
|
||||
ReverbSCControlDialog.h
|
||||
base.h
|
||||
revsc.h
|
||||
dcblock.h
|
||||
dcblock.c
|
||||
ReverbSC.h
|
||||
MOCFILES
|
||||
ReverbSCControls.h
|
||||
ReverbSCControlDialog.h
|
||||
EMBEDDED_RESOURCES artwork.png logo.png
|
||||
)
|
||||
|
||||
@@ -58,8 +58,8 @@ ReverbSCEffect::ReverbSCEffect( Model* parent, const Descriptor::SubPluginFeatur
|
||||
sp_dcblock_create(&dcblk[0]);
|
||||
sp_dcblock_create(&dcblk[1]);
|
||||
|
||||
sp_dcblock_init(sp, dcblk[0]);
|
||||
sp_dcblock_init(sp, dcblk[1]);
|
||||
sp_dcblock_init(sp, dcblk[0], Engine::mixer()->currentQualitySettings().sampleRateMultiplier() );
|
||||
sp_dcblock_init(sp, dcblk[1], Engine::mixer()->currentQualitySettings().sampleRateMultiplier() );
|
||||
}
|
||||
|
||||
ReverbSCEffect::~ReverbSCEffect()
|
||||
@@ -125,6 +125,27 @@ bool ReverbSCEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
|
||||
|
||||
return isRunning();
|
||||
}
|
||||
|
||||
void ReverbSCEffect::changeSampleRate()
|
||||
{
|
||||
// Change sr variable in Soundpipe. does not need to be destroyed
|
||||
sp->sr = Engine::mixer()->processingSampleRate();
|
||||
|
||||
mutex.lock();
|
||||
sp_revsc_destroy(&revsc);
|
||||
sp_dcblock_destroy(&dcblk[0]);
|
||||
sp_dcblock_destroy(&dcblk[1]);
|
||||
|
||||
sp_revsc_create(&revsc);
|
||||
sp_revsc_init(sp, revsc);
|
||||
|
||||
sp_dcblock_create(&dcblk[0]);
|
||||
sp_dcblock_create(&dcblk[1]);
|
||||
|
||||
sp_dcblock_init(sp, dcblk[0], Engine::mixer()->currentQualitySettings().sampleRateMultiplier() );
|
||||
sp_dcblock_init(sp, dcblk[1], Engine::mixer()->currentQualitySettings().sampleRateMultiplier() );
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
@@ -48,12 +48,14 @@ public:
|
||||
return &m_reverbSCControls;
|
||||
}
|
||||
|
||||
void changeSampleRate();
|
||||
|
||||
private:
|
||||
ReverbSCControls m_reverbSCControls;
|
||||
sp_data *sp;
|
||||
sp_revsc *revsc;
|
||||
sp_dcblock *dcblk[2];
|
||||
QMutex mutex;
|
||||
friend class ReverbSCControls;
|
||||
} ;
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ ReverbSCControls::ReverbSCControls( ReverbSCEffect* effect ) :
|
||||
m_colorModel( 10000.0f, 100.0f, 15000.0f, 0.1f, this, tr( "Color" ) ),
|
||||
m_outputGainModel( 0.0f, -60.0f, 15, 0.1f, this, tr( "Output Gain" ) )
|
||||
{
|
||||
connect( Engine::mixer(), SIGNAL( sampleRateChanged() ), this, SLOT( changeSampleRate() ));
|
||||
}
|
||||
|
||||
void ReverbSCControls::changeControl()
|
||||
@@ -60,3 +61,7 @@ void ReverbSCControls::saveSettings( QDomDocument& doc, QDomElement& _this )
|
||||
m_outputGainModel.saveSettings( doc, _this, "output_gain" );
|
||||
}
|
||||
|
||||
void ReverbSCControls::changeSampleRate()
|
||||
{
|
||||
m_effect->changeSampleRate();
|
||||
}
|
||||
|
||||
@@ -61,6 +61,7 @@ public:
|
||||
|
||||
private slots:
|
||||
void changeControl();
|
||||
void changeSampleRate();
|
||||
|
||||
private:
|
||||
ReverbSCEffect* m_effect;
|
||||
|
||||
@@ -25,7 +25,7 @@ typedef struct sp_auxdata {
|
||||
|
||||
typedef struct sp_data {
|
||||
SPFLOAT *out;
|
||||
int sr;
|
||||
uint32_t sr;
|
||||
int nchan;
|
||||
unsigned long len;
|
||||
unsigned long pos;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include "base.h"
|
||||
#include "dcblock.h"
|
||||
@@ -26,11 +27,11 @@ int sp_dcblock_destroy(sp_dcblock **p)
|
||||
return SP_OK;
|
||||
}
|
||||
|
||||
int sp_dcblock_init(sp_data *sp, sp_dcblock *p)
|
||||
int sp_dcblock_init(sp_data *sp, sp_dcblock *p, int oversampling )
|
||||
{
|
||||
p->outputs = 0.0;
|
||||
p->inputs = 0.0;
|
||||
p->gain = 0.99;
|
||||
p->gain = pow( 0.99, 1.0f / oversampling );
|
||||
if (p->gain == 0.0 || p->gain>=1.0 || p->gain<=-1.0)
|
||||
p->gain = 0.99;
|
||||
return SP_OK;
|
||||
|
||||
@@ -7,5 +7,5 @@ typedef struct {
|
||||
|
||||
int sp_dcblock_create(sp_dcblock **p);
|
||||
int sp_dcblock_destroy(sp_dcblock **p);
|
||||
int sp_dcblock_init(sp_data *sp, sp_dcblock *p);
|
||||
int sp_dcblock_init(sp_data *sp, sp_dcblock *p, int oversampling );
|
||||
int sp_dcblock_compute(sp_data *sp, sp_dcblock *p, SPFLOAT *in, SPFLOAT *out);
|
||||
|
||||
@@ -87,10 +87,10 @@ VstEffectControlDialog::VstEffectControlDialog( VstEffectControls * _ctl ) :
|
||||
m_managePluginButton = new PixmapButton( this, "" );
|
||||
m_managePluginButton->setCheckable( false );
|
||||
m_managePluginButton->setCursor( Qt::PointingHandCursor );
|
||||
m_managePluginButton->setActiveGraphic( embed::getIconPixmap(
|
||||
"track_op_menu_active" ) );
|
||||
m_managePluginButton->setInactiveGraphic( embed::getIconPixmap(
|
||||
"track_op_menu" ) );
|
||||
m_managePluginButton->setActiveGraphic( PLUGIN_NAME::getIconPixmap(
|
||||
"controls_active" ) );
|
||||
m_managePluginButton->setInactiveGraphic( PLUGIN_NAME::getIconPixmap(
|
||||
"controls" ) );
|
||||
connect( m_managePluginButton, SIGNAL( clicked() ), _ctl,
|
||||
SLOT( managePlugin() ) );
|
||||
ToolTip::add( m_managePluginButton, tr( "Control VST-plugin from LMMS host" ) );
|
||||
@@ -98,8 +98,8 @@ VstEffectControlDialog::VstEffectControlDialog( VstEffectControls * _ctl ) :
|
||||
m_managePluginButton->setWhatsThis(
|
||||
tr( "Click here, if you want to control VST-plugin from host." ) );
|
||||
|
||||
m_managePluginButton->setMinimumWidth( 21 );
|
||||
m_managePluginButton->setMaximumWidth( 21 );
|
||||
m_managePluginButton->setMinimumWidth( 26 );
|
||||
m_managePluginButton->setMaximumWidth( 26 );
|
||||
m_managePluginButton->setMinimumHeight( 21 );
|
||||
m_managePluginButton->setMaximumHeight( 21 );
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 841 B After Width: | Height: | Size: 841 B |
|
Before Width: | Height: | Size: 824 B After Width: | Height: | Size: 824 B |
@@ -1081,7 +1081,6 @@ void sf2InstrumentView::showFileDialog()
|
||||
types << tr( "SoundFont2 Files (*.sf2)" );
|
||||
ofd.setNameFilters( types );
|
||||
|
||||
QString dir;
|
||||
if( k->m_filename != "" )
|
||||
{
|
||||
QString f = SampleBuffer::tryToMakeAbsolute( k->m_filename );
|
||||
|
||||
BIN
plugins/vestige/controls.png
Normal file
|
After Width: | Height: | Size: 841 B |
BIN
plugins/vestige/controls_active.png
Normal file
|
After Width: | Height: | Size: 824 B |
@@ -42,6 +42,7 @@
|
||||
#include "Mixer.h"
|
||||
#include "GuiApplication.h"
|
||||
#include "PixmapButton.h"
|
||||
#include "SampleBuffer.h"
|
||||
#include "StringPairDrag.h"
|
||||
#include "TextFloat.h"
|
||||
#include "ToolTip.h"
|
||||
@@ -174,17 +175,6 @@ void vestigeInstrument::setParameter( void )
|
||||
|
||||
void vestigeInstrument::saveSettings( QDomDocument & _doc, QDomElement & _this )
|
||||
{
|
||||
if( QFileInfo( m_pluginDLL ).isAbsolute() )
|
||||
{
|
||||
QString f = QString( m_pluginDLL ).replace( QDir::separator(), '/' );
|
||||
QString vd = QString( ConfigManager::inst()->vstDir() ).replace( QDir::separator(), '/' );
|
||||
QString relativePath;
|
||||
if( !( relativePath = f.section( vd, 1, 1 ) ).isEmpty() )
|
||||
{
|
||||
m_pluginDLL = relativePath;
|
||||
}
|
||||
}
|
||||
|
||||
_this.setAttribute( "plugin", m_pluginDLL );
|
||||
m_pluginMutex.lock();
|
||||
if( m_plugin != NULL )
|
||||
@@ -254,8 +244,7 @@ void vestigeInstrument::loadFile( const QString & _file )
|
||||
{
|
||||
closePlugin();
|
||||
}
|
||||
|
||||
m_pluginDLL = _file;
|
||||
m_pluginDLL = SampleBuffer::tryToMakeRelative( _file );
|
||||
TextFloat * tf = TextFloat::displayMessage(
|
||||
tr( "Loading plugin" ),
|
||||
tr( "Please wait while loading VST-plugin..." ),
|
||||
@@ -269,6 +258,7 @@ void vestigeInstrument::loadFile( const QString & _file )
|
||||
closePlugin();
|
||||
delete tf;
|
||||
collectErrorForUI( VstPlugin::tr( "The VST plugin %1 could not be loaded." ).arg( m_pluginDLL ) );
|
||||
m_pluginDLL = "";
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -425,10 +415,10 @@ VestigeInstrumentView::VestigeInstrumentView( Instrument * _instrument,
|
||||
m_managePluginButton->setCheckable( false );
|
||||
m_managePluginButton->setCursor( Qt::PointingHandCursor );
|
||||
m_managePluginButton->move( 216, 101 );
|
||||
m_managePluginButton->setActiveGraphic( embed::getIconPixmap(
|
||||
"track_op_menu_active" ) );
|
||||
m_managePluginButton->setInactiveGraphic( embed::getIconPixmap(
|
||||
"track_op_menu" ) );
|
||||
m_managePluginButton->setActiveGraphic( PLUGIN_NAME::getIconPixmap(
|
||||
"controls_active" ) );
|
||||
m_managePluginButton->setInactiveGraphic( PLUGIN_NAME::getIconPixmap(
|
||||
"controls" ) );
|
||||
connect( m_managePluginButton, SIGNAL( clicked() ), this,
|
||||
SLOT( managePlugin() ) );
|
||||
ToolTip::add( m_managePluginButton, tr( "Control VST-plugin from LMMS host" ) );
|
||||
@@ -614,29 +604,22 @@ void VestigeInstrumentView::openPlugin()
|
||||
{
|
||||
FileDialog ofd( NULL, tr( "Open VST-plugin" ) );
|
||||
|
||||
QString dir;
|
||||
if( m_vi->m_pluginDLL != "" )
|
||||
{
|
||||
dir = QFileInfo( m_vi->m_pluginDLL ).absolutePath();
|
||||
}
|
||||
else
|
||||
{
|
||||
dir = ConfigManager::inst()->vstDir();
|
||||
}
|
||||
// change dir to position of previously opened file
|
||||
ofd.setDirectory( dir );
|
||||
ofd.setFileMode( FileDialog::ExistingFiles );
|
||||
|
||||
// set filters
|
||||
QStringList types;
|
||||
types << tr( "DLL-files (*.dll)" )
|
||||
<< tr( "EXE-files (*.exe)" )
|
||||
;
|
||||
ofd.setNameFilters( types );
|
||||
|
||||
if( m_vi->m_pluginDLL != "" )
|
||||
{
|
||||
// select previously opened file
|
||||
ofd.selectFile( QFileInfo( m_vi->m_pluginDLL ).fileName() );
|
||||
QString f = SampleBuffer::tryToMakeAbsolute( m_vi->m_pluginDLL );
|
||||
ofd.setDirectory( QFileInfo( f ).absolutePath() );
|
||||
ofd.selectFile( QFileInfo( f ).fileName() );
|
||||
}
|
||||
else
|
||||
{
|
||||
ofd.setDirectory( ConfigManager::inst()->vstDir() );
|
||||
}
|
||||
|
||||
if ( ofd.exec () == QDialog::Accepted )
|
||||
|
||||
@@ -34,20 +34,20 @@ IF(LMMS_BUILD_LINUX AND NOT WANT_VST_NOWINE)
|
||||
IF(LMMS_HOST_X86_64)
|
||||
SET(EXTRA_FLAGS -m32)
|
||||
|
||||
# workaround for broken wineg++ in WINE 1.4 (shipped e.g. with Ubuntu Precise)
|
||||
EXEC_PROGRAM( ${WINE_CXX} ARGS "-v -m32 /dev/zero" OUTPUT_VARIABLE WINEBUILD_OUTPUT)
|
||||
# workaround for broken wineg++ in WINE 1.4 (shipped e.g. with Ubuntu Precise)
|
||||
IF("${WINEBUILD_OUTPUT}" MATCHES ".*x86_64-linux-gnu/wine/libwinecrt0.a.*")
|
||||
SET(EXTRA_FLAGS ${EXTRA_FLAGS} -nodefaultlibs /usr/lib/i386-linux-gnu/wine/libwinecrt0.a -luser32 -lkernel32 -lgdi32)
|
||||
SET(EXTRA_FLAGS ${EXTRA_FLAGS} -nodefaultlibs /usr/lib/i386-linux-gnu/wine/libwinecrt0.a -L/usr/lib/i386-linux-gnu/wine/ -luser32 -lkernel32 -lgdi32)
|
||||
ENDIF()
|
||||
# The following check works on Fedora systems
|
||||
IF("${WINEBUILD_OUTPUT}" MATCHES "/usr/lib/lib64/wine/libwinecrt0.a.*")
|
||||
SET(EXTRA_FLAGS ${EXTRA_FLAGS} -nodefaultlibs /usr/lib/i386/wine/libwinecrt0.a -luser32 -lkernel32 -lgdi32)
|
||||
ENDIF()
|
||||
# Development
|
||||
# Wine development
|
||||
IF("${WINEBUILD_OUTPUT}" MATCHES "/opt/wine-devel/lib64/wine/libwinecrt0.a.*")
|
||||
SET(EXTRA_FLAGS ${EXTRA_FLAGS} -nodefaultlibs /opt/wine-devel/lib/wine/libwinecrt0.a -luser32 -lkernel32 -lgdi32)
|
||||
ENDIF()
|
||||
# Staging
|
||||
# Wine staging
|
||||
IF("${WINEBUILD_OUTPUT}" MATCHES "/opt/wine-staging/lib64/wine/libwinecrt0.a.*")
|
||||
SET(EXTRA_FLAGS ${EXTRA_FLAGS} -nodefaultlibs /opt/wine-staging/lib/wine/libwinecrt0.a -luser32 -lkernel32 -lgdi32)
|
||||
ENDIF()
|
||||
@@ -61,16 +61,15 @@ STRING(REPLACE " " ";" WINE_BUILD_FLAGS ${CMAKE_CXX_FLAGS} " " ${CMAKE_EXE_LINKE
|
||||
ADD_CUSTOM_COMMAND(
|
||||
SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/RemoteVstPlugin.cpp"
|
||||
COMMAND ${WINE_CXX}
|
||||
ARGS "-I\"${CMAKE_BINARY_DIR}\""
|
||||
"-I\"${CMAKE_SOURCE_DIR}/include\""
|
||||
"-I\"${CMAKE_INSTALL_PREFIX}/include/wine/windows\""
|
||||
"-I\"${CMAKE_INSTALL_PREFIX}/include\""
|
||||
"-I\"${WINE_INCLUDE_BASE_DIR}\""
|
||||
"-L\"${WINE_LIBRARY_DIR}\""
|
||||
"\"${CMAKE_CURRENT_SOURCE_DIR}/RemoteVstPlugin.cpp\""
|
||||
ARGS -I${CMAKE_BINARY_DIR}
|
||||
-I${CMAKE_SOURCE_DIR}/include
|
||||
-I${WINE_INCLUDE_BASE_DIR}
|
||||
-L${WINE_LIBRARY_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/RemoteVstPlugin.cpp
|
||||
-ansi -mwindows -lpthread ${EXTRA_FLAGS} -fno-omit-frame-pointer
|
||||
${WINE_BUILD_FLAGS}
|
||||
-o ../RemoteVstPlugin
|
||||
# Ensure correct file extension
|
||||
COMMAND sh -c "mv ../RemoteVstPlugin.exe ../RemoteVstPlugin || true"
|
||||
TARGET vstbase
|
||||
OUTPUTS ../RemoteVstPlugin
|
||||
|
||||
@@ -75,6 +75,10 @@ IF(NOT ("${OGGVORBIS_INCLUDE_DIR}" STREQUAL ""))
|
||||
INCLUDE_DIRECTORIES("${OGGVORBIS_INCLUDE_DIR}")
|
||||
ENDIF()
|
||||
|
||||
IF(NOT ("${LAME_INCLUDE_DIRS}" STREQUAL ""))
|
||||
INCLUDE_DIRECTORIES("${LAME_INCLUDE_DIRS}")
|
||||
ENDIF()
|
||||
|
||||
# Use libraries in non-standard directories (e.g., another version of Qt)
|
||||
IF(LMMS_BUILD_LINUX)
|
||||
LINK_LIBRARIES(-Wl,--enable-new-dtags)
|
||||
@@ -136,6 +140,7 @@ SET(LMMS_REQUIRED_LIBS
|
||||
${PULSEAUDIO_LIBRARIES}
|
||||
${JACK_LIBRARIES}
|
||||
${OGGVORBIS_LIBRARIES}
|
||||
${LAME_LIBRARIES}
|
||||
${SAMPLERATE_LIBRARIES}
|
||||
${SNDFILE_LIBRARIES}
|
||||
${EXTRA_LIBRARIES}
|
||||
@@ -191,6 +196,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}/bin/libmp3lame-0.dll"
|
||||
"${MINGW_PREFIX}/bin/libfftw3f-3.dll"
|
||||
"${MINGW_PREFIX}/bin/libFLAC-8.dll"
|
||||
"${MINGW_PREFIX}/bin/libpng16-16.dll"
|
||||
|
||||
@@ -716,19 +716,19 @@ float AutomatableModel::globalAutomationValueAt( const MidiTime& time )
|
||||
|
||||
float FloatModel::getRoundedValue() const
|
||||
{
|
||||
return static_cast<float>( static_cast<int>( value() / step<float>() + 0.5 ) ) * step<float>();
|
||||
return qRound( value() / step<float>() ) * step<float>();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
float FloatModel::getDigitCount()
|
||||
int FloatModel::getDigitCount() const
|
||||
{
|
||||
float steptemp = step<float>();
|
||||
int digits = 0;
|
||||
while ( steptemp < 1 )
|
||||
{
|
||||
steptemp = steptemp / 0.1f;
|
||||
steptemp = steptemp * 10.0f;
|
||||
digits++;
|
||||
}
|
||||
return digits;
|
||||
|
||||
@@ -69,6 +69,7 @@ set(LMMS_SRCS
|
||||
core/audio/AudioAlsa.cpp
|
||||
core/audio/AudioDevice.cpp
|
||||
core/audio/AudioFileDevice.cpp
|
||||
core/audio/AudioFileMP3.cpp
|
||||
core/audio/AudioFileOgg.cpp
|
||||
core/audio/AudioFileWave.cpp
|
||||
core/audio/AudioJack.cpp
|
||||
|
||||
@@ -63,7 +63,12 @@ ConfigManager::ConfigManager() :
|
||||
|
||||
// If we're in development (lmms is not installed) let's get the source and
|
||||
// binary directories by reading the CMake Cache
|
||||
QFile cmakeCache(qApp->applicationDirPath() + "/CMakeCache.txt");
|
||||
QDir appPath = qApp->applicationDirPath();
|
||||
// If in tests, get parent directory
|
||||
if (appPath.dirName() == "tests") {
|
||||
appPath.cdUp();
|
||||
}
|
||||
QFile cmakeCache(appPath.absoluteFilePath("CMakeCache.txt"));
|
||||
if (cmakeCache.exists()) {
|
||||
cmakeCache.open(QFile::ReadOnly);
|
||||
QTextStream stream(&cmakeCache);
|
||||
@@ -277,7 +282,8 @@ void ConfigManager::addRecentlyOpenedProject( const QString & file )
|
||||
{
|
||||
QFileInfo recentFile( file );
|
||||
if( recentFile.suffix().toLower() == "mmp" ||
|
||||
recentFile.suffix().toLower() == "mmpz" )
|
||||
recentFile.suffix().toLower() == "mmpz" ||
|
||||
recentFile.suffix().toLower() == "mpt" )
|
||||
{
|
||||
m_recentlyOpenedProjects.removeAll( file );
|
||||
if( m_recentlyOpenedProjects.size() > 50 )
|
||||
@@ -313,6 +319,16 @@ const QString & ConfigManager::value( const QString & cls,
|
||||
|
||||
|
||||
|
||||
const QString & ConfigManager::value( const QString & cls,
|
||||
const QString & attribute,
|
||||
const QString & defaultVal ) const
|
||||
{
|
||||
const QString & val = value( cls, attribute );
|
||||
return val.isEmpty() ? defaultVal : val;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void ConfigManager::setValue( const QString & cls,
|
||||
const QString & attribute,
|
||||
|
||||
@@ -113,6 +113,7 @@ void LfoController::updateValueBuffer()
|
||||
}
|
||||
|
||||
m_currentPhase = absFraction( phase - m_phaseOffset );
|
||||
m_bufferLastUpdated = s_periods;
|
||||
}
|
||||
|
||||
void LfoController::updatePhase()
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
#include "AudioFileWave.h"
|
||||
#include "AudioFileOgg.h"
|
||||
#include "AudioFileMP3.h"
|
||||
|
||||
#ifdef LMMS_HAVE_SCHED_H
|
||||
#include "sched.h"
|
||||
@@ -48,6 +49,15 @@ const ProjectRenderer::FileEncodeDevice ProjectRenderer::fileEncodeDevices[] =
|
||||
&AudioFileOgg::getInst
|
||||
#else
|
||||
NULL
|
||||
#endif
|
||||
},
|
||||
{ ProjectRenderer::MP3File,
|
||||
QT_TRANSLATE_NOOP( "ProjectRenderer", "Compressed MP3-File (*.mp3)" ),
|
||||
".mp3",
|
||||
#ifdef LMMS_HAVE_MP3LAME
|
||||
&AudioFileMP3::getInst
|
||||
#else
|
||||
NULL
|
||||
#endif
|
||||
},
|
||||
// ... insert your own file-encoder-infos here... may be one day the
|
||||
@@ -93,6 +103,8 @@ ProjectRenderer::ProjectRenderer( const Mixer::qualitySettings & qualitySettings
|
||||
|
||||
ProjectRenderer::~ProjectRenderer()
|
||||
{
|
||||
Engine::mixer()->restoreAudioDevice(); // also deletes audio-dev
|
||||
Engine::mixer()->changeQuality( m_oldQualitySettings );
|
||||
}
|
||||
|
||||
|
||||
@@ -172,10 +184,11 @@ void ProjectRenderer::run()
|
||||
m_progress = 0;
|
||||
std::pair<MidiTime, MidiTime> exportEndpoints = Engine::getSong()->getExportEndpoints();
|
||||
tick_t startTick = exportEndpoints.first.getTicks();
|
||||
tick_t lengthTicks = exportEndpoints.second.getTicks() - startTick;
|
||||
tick_t endTick = exportEndpoints.second.getTicks();
|
||||
tick_t lengthTicks = endTick - startTick;
|
||||
|
||||
// Continually track and emit progress percentage to listeners
|
||||
while( Engine::getSong()->isExportDone() == false &&
|
||||
while( exportPos.getTicks() < endTick &&
|
||||
Engine::getSong()->isExporting() == true
|
||||
&& !m_abort )
|
||||
{
|
||||
@@ -190,12 +203,8 @@ void ProjectRenderer::run()
|
||||
|
||||
Engine::getSong()->stopExport();
|
||||
|
||||
const QString f = m_fileDev->outputFile();
|
||||
|
||||
Engine::mixer()->restoreAudioDevice(); // also deletes audio-dev
|
||||
Engine::mixer()->changeQuality( m_oldQualitySettings );
|
||||
|
||||
// if the user aborted export-process, the file has to be deleted
|
||||
const QString f = m_fileDev->outputFile();
|
||||
if( m_abort )
|
||||
{
|
||||
QFile( f ).remove();
|
||||
|
||||
@@ -1411,25 +1411,35 @@ void SampleBuffer::setReversed( bool _on )
|
||||
|
||||
|
||||
|
||||
QString SampleBuffer::tryToMakeRelative( const QString & _file )
|
||||
QString SampleBuffer::tryToMakeRelative( const QString & file )
|
||||
{
|
||||
if( QFileInfo( _file ).isRelative() == false )
|
||||
if( QFileInfo( file ).isRelative() == false )
|
||||
{
|
||||
QString f = QString( _file ).replace( QDir::separator(), '/' );
|
||||
QString fsd = ConfigManager::inst()->factorySamplesDir();
|
||||
QString usd = ConfigManager::inst()->userSamplesDir();
|
||||
fsd.replace( QDir::separator(), '/' );
|
||||
usd.replace( QDir::separator(), '/' );
|
||||
if( f.startsWith( fsd ) )
|
||||
QString f = QString( file ).replace( QDir::separator(), '/' );
|
||||
|
||||
// First, look in factory samples
|
||||
// Isolate "samples/" from "data:/samples/"
|
||||
QString samplesSuffix = ConfigManager::inst()->factorySamplesDir().mid( ConfigManager::inst()->dataDir().length() );
|
||||
|
||||
// Iterate over all valid "data:/" searchPaths
|
||||
for ( const QString & path : QDir::searchPaths( "data" ) )
|
||||
{
|
||||
return QString( f ).mid( fsd.length() );
|
||||
QString samplesPath = QString( path + samplesSuffix ).replace( QDir::separator(), '/' );
|
||||
if ( f.startsWith( samplesPath ) )
|
||||
{
|
||||
return QString( f ).mid( samplesPath.length() );
|
||||
}
|
||||
}
|
||||
else if( f.startsWith( usd ) )
|
||||
|
||||
// Next, look in user samples
|
||||
QString usd = ConfigManager::inst()->userSamplesDir();
|
||||
usd.replace( QDir::separator(), '/' );
|
||||
if( f.startsWith( usd ) )
|
||||
{
|
||||
return QString( f ).mid( usd.length() );
|
||||
}
|
||||
}
|
||||
return _file;
|
||||
return file;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -464,29 +464,6 @@ void Song::processAutomations(const TrackList &tracklist, MidiTime timeStart, fp
|
||||
}
|
||||
}
|
||||
|
||||
bool Song::isExportDone() const
|
||||
{
|
||||
if ( m_renderBetweenMarkers )
|
||||
{
|
||||
return m_exporting == true &&
|
||||
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();
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_exporting == true &&
|
||||
m_playPos[Mode_PlaySong].getTicks() >=
|
||||
( length() + 1 ) * ticksPerTact();
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<MidiTime, MidiTime> Song::getExportEndpoints() const
|
||||
{
|
||||
if ( m_renderBetweenMarkers )
|
||||
@@ -1077,6 +1054,27 @@ void Song::loadProject( const QString & fileName )
|
||||
}
|
||||
|
||||
node = dataFile.content().firstChild();
|
||||
|
||||
QDomNodeList tclist=dataFile.content().elementsByTagName("trackcontainer");
|
||||
m_nLoadingTrack=0;
|
||||
for( int i=0,n=tclist.count(); i<n; ++i )
|
||||
{
|
||||
QDomNode nd=tclist.at(i).firstChild();
|
||||
while(!nd.isNull())
|
||||
{
|
||||
if( nd.isElement() && nd.nodeName() == "track" )
|
||||
{
|
||||
++m_nLoadingTrack;
|
||||
if( nd.toElement().attribute("type").toInt() == Track::BBTrack )
|
||||
{
|
||||
n += nd.toElement().elementsByTagName("bbtrack").at(0)
|
||||
.toElement().firstChildElement().childNodes().count();
|
||||
}
|
||||
nd=nd.nextSibling();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while( !node.isNull() )
|
||||
{
|
||||
if( node.isElement() )
|
||||
@@ -1339,7 +1337,8 @@ void Song::exportProject( bool multiExport )
|
||||
efd.setFileMode( FileDialog::AnyFile );
|
||||
int idx = 0;
|
||||
QStringList types;
|
||||
while( ProjectRenderer::fileEncodeDevices[idx].m_fileFormat != ProjectRenderer::NumFileFormats )
|
||||
while( ProjectRenderer::fileEncodeDevices[idx].m_fileFormat != ProjectRenderer::NumFileFormats &&
|
||||
ProjectRenderer::fileEncodeDevices[idx].isAvailable())
|
||||
{
|
||||
types << tr( ProjectRenderer::fileEncodeDevices[idx].m_description );
|
||||
++idx;
|
||||
@@ -1360,13 +1359,14 @@ void Song::exportProject( bool multiExport )
|
||||
efd.setWindowTitle( tr( "Select file for project-export..." ) );
|
||||
}
|
||||
|
||||
QString suffix = "wav";
|
||||
efd.setDefaultSuffix( suffix );
|
||||
efd.setAcceptMode( FileDialog::AcceptSave );
|
||||
|
||||
|
||||
if( efd.exec() == QDialog::Accepted && !efd.selectedFiles().isEmpty() &&
|
||||
!efd.selectedFiles()[0].isEmpty() )
|
||||
{
|
||||
QString suffix = "";
|
||||
|
||||
QString exportFileName = efd.selectedFiles()[0];
|
||||
if ( !multiExport )
|
||||
{
|
||||
@@ -1378,19 +1378,18 @@ void Song::exportProject( bool multiExport )
|
||||
// Get first extension from selected dropdown.
|
||||
// i.e. ".wav" from "WAV-File (*.wav), Dummy-File (*.dum)"
|
||||
suffix = efd.selectedNameFilter().mid( stx + 2, etx - stx - 2 ).split( " " )[0].trimmed();
|
||||
exportFileName.remove( "." + suffix, Qt::CaseInsensitive );
|
||||
if ( efd.selectedFiles()[0].endsWith( suffix ) )
|
||||
{
|
||||
suffix = "";
|
||||
if( VersionedSaveDialog::fileExistsQuery( exportFileName + suffix,
|
||||
tr( "Save project" ) ) )
|
||||
{
|
||||
exportFileName += suffix;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( VersionedSaveDialog::fileExistsQuery( exportFileName + suffix,
|
||||
tr( "Save project" ) ) )
|
||||
{
|
||||
exportFileName += suffix;
|
||||
}
|
||||
|
||||
ExportProjectDialog epd( exportFileName, gui->mainWindow(), multiExport );
|
||||
epd.exec();
|
||||
}
|
||||
|
||||
@@ -86,25 +86,18 @@ void TrackContainer::loadSettings( const QDomElement & _this )
|
||||
|
||||
static QProgressDialog * pd = NULL;
|
||||
bool was_null = ( pd == NULL );
|
||||
int start_val = 0;
|
||||
if( !journalRestore && gui != nullptr )
|
||||
{
|
||||
if( pd == NULL )
|
||||
{
|
||||
pd = new QProgressDialog( tr( "Loading project..." ),
|
||||
tr( "Cancel" ), 0,
|
||||
_this.childNodes().count(),
|
||||
Engine::getSong()->getLoadingTrackCount(),
|
||||
gui->mainWindow() );
|
||||
pd->setWindowModality( Qt::ApplicationModal );
|
||||
pd->setWindowTitle( tr( "Please wait..." ) );
|
||||
pd->show();
|
||||
}
|
||||
else
|
||||
{
|
||||
start_val = pd->value();
|
||||
pd->setMaximum( pd->maximum() +
|
||||
_this.childNodes().count() );
|
||||
}
|
||||
}
|
||||
|
||||
QDomNode node = _this.firstChild();
|
||||
@@ -124,6 +117,14 @@ void TrackContainer::loadSettings( const QDomElement & _this )
|
||||
if( node.isElement() &&
|
||||
!node.toElement().attribute( "metadata" ).toInt() )
|
||||
{
|
||||
QString trackName = node.toElement().hasAttribute( "name" ) ?
|
||||
node.toElement().attribute( "name" ) :
|
||||
node.firstChild().toElement().attribute( "name" );
|
||||
if( pd != NULL )
|
||||
{
|
||||
pd->setLabelText( tr("Loading Track %1 (%2/Total %3)").arg( trackName ).
|
||||
arg( pd->value() + 1 ).arg( Engine::getSong()->getLoadingTrackCount() ) );
|
||||
}
|
||||
Track::create( node.toElement(), this );
|
||||
}
|
||||
node = node.nextSibling();
|
||||
@@ -131,7 +132,6 @@ void TrackContainer::loadSettings( const QDomElement & _this )
|
||||
|
||||
if( pd != NULL )
|
||||
{
|
||||
pd->setValue( start_val + _this.childNodes().count() );
|
||||
if( was_null )
|
||||
{
|
||||
delete pd;
|
||||
|
||||
133
src/core/audio/AudioFileMP3.cpp
Normal file
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* AudioFileMP3.cpp - Audio-device which encodes a wave stream into
|
||||
* an MP3 file. This is used for song export.
|
||||
*
|
||||
* Copyright (c) 2017 to present Michael Gregorius <michael.gregorius.git/at/arcor[dot]de>
|
||||
*
|
||||
* This file is part of LMMS - https://lmms.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "AudioFileMP3.h"
|
||||
|
||||
#ifdef LMMS_HAVE_MP3LAME
|
||||
|
||||
#include "Mixer.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
|
||||
AudioFileMP3::AudioFileMP3( OutputSettings const & outputSettings,
|
||||
const ch_cnt_t channels,
|
||||
bool & successful,
|
||||
const QString & file,
|
||||
Mixer* mixer ) :
|
||||
AudioFileDevice( outputSettings, channels, file, mixer )
|
||||
{
|
||||
successful = true;
|
||||
// For now only accept stereo sources
|
||||
successful &= channels == 2;
|
||||
successful &= initEncoder();
|
||||
successful &= outputFileOpened();
|
||||
}
|
||||
|
||||
AudioFileMP3::~AudioFileMP3()
|
||||
{
|
||||
flushRemainingBuffers();
|
||||
tearDownEncoder();
|
||||
}
|
||||
|
||||
void AudioFileMP3::writeBuffer( const surroundSampleFrame * _buf,
|
||||
const fpp_t _frames,
|
||||
const float _master_gain )
|
||||
{
|
||||
if (_frames < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO Why isn't the gain applied by the driver but inside the device?
|
||||
std::vector<float> interleavedDataBuffer(_frames * 2);
|
||||
for (fpp_t i = 0; i < _frames; ++i)
|
||||
{
|
||||
interleavedDataBuffer[2*i] = _buf[i][0] * _master_gain;
|
||||
interleavedDataBuffer[2*i + 1] = _buf[i][1] * _master_gain;
|
||||
}
|
||||
|
||||
size_t minimumBufferSize = 1.25 * _frames + 7200;
|
||||
std::vector<unsigned char> encodingBuffer(minimumBufferSize);
|
||||
|
||||
int bytesWritten = lame_encode_buffer_interleaved_ieee_float(m_lame, &interleavedDataBuffer[0], _frames, &encodingBuffer[0], static_cast<int>(encodingBuffer.size()));
|
||||
assert (bytesWritten >= 0);
|
||||
|
||||
writeData(&encodingBuffer[0], bytesWritten);
|
||||
}
|
||||
|
||||
void AudioFileMP3::flushRemainingBuffers()
|
||||
{
|
||||
// The documentation states that flush should have at least 7200 bytes. So let's be generous.
|
||||
std::vector<unsigned char> encodingBuffer(7200 * 4);
|
||||
|
||||
int bytesWritten = lame_encode_flush(m_lame, &encodingBuffer[0], static_cast<int>(encodingBuffer.size()));
|
||||
assert (bytesWritten >= 0);
|
||||
|
||||
writeData(&encodingBuffer[0], bytesWritten);
|
||||
}
|
||||
|
||||
MPEG_mode mapToMPEG_mode(OutputSettings::StereoMode stereoMode)
|
||||
{
|
||||
switch (stereoMode)
|
||||
{
|
||||
case OutputSettings::StereoMode_Stereo:
|
||||
return STEREO;
|
||||
case OutputSettings::StereoMode_JointStereo:
|
||||
return JOINT_STEREO;
|
||||
case OutputSettings::StereoMode_Mono:
|
||||
return MONO;
|
||||
default:
|
||||
return NOT_SET;
|
||||
}
|
||||
}
|
||||
|
||||
bool AudioFileMP3::initEncoder()
|
||||
{
|
||||
m_lame = lame_init();
|
||||
|
||||
// Handle stereo/joint/mono settings
|
||||
OutputSettings::StereoMode stereoMode = getOutputSettings().getStereoMode();
|
||||
lame_set_mode(m_lame, mapToMPEG_mode(stereoMode));
|
||||
|
||||
// Handle bit rate settings
|
||||
OutputSettings::BitRateSettings bitRateSettings = getOutputSettings().getBitRateSettings();
|
||||
int bitRate = static_cast<int>(bitRateSettings.getBitRate());
|
||||
|
||||
lame_set_VBR(m_lame, vbr_off);
|
||||
lame_set_brate(m_lame, bitRate);
|
||||
|
||||
// Add a comment
|
||||
id3tag_set_comment(m_lame, "Created with LMMS");
|
||||
|
||||
return lame_init_params(m_lame) != -1;
|
||||
}
|
||||
|
||||
void AudioFileMP3::tearDownEncoder()
|
||||
{
|
||||
lame_close(m_lame);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -70,8 +70,7 @@ inline int AudioFileOgg::writePage()
|
||||
bool AudioFileOgg::startEncoding()
|
||||
{
|
||||
vorbis_comment vc;
|
||||
const char * comments = "Cool=This song has been made using Linux "
|
||||
"MultiMedia Studio";
|
||||
const char * comments = "Cool=This song has been made using LMMS";
|
||||
int comment_length = strlen( comments );
|
||||
char * user_comments = new char[comment_length + 1];
|
||||
strcpy( user_comments, comments );
|
||||
@@ -100,7 +99,7 @@ bool AudioFileOgg::startEncoding()
|
||||
m_rate = 48000;
|
||||
setSampleRate( 48000 );
|
||||
}
|
||||
m_serialNo = 0; // track-num?
|
||||
|
||||
m_comments = &vc; // comments for ogg-file
|
||||
|
||||
// Have vorbisenc choose a mode for us
|
||||
@@ -135,6 +134,10 @@ bool AudioFileOgg::startEncoding()
|
||||
vorbis_analysis_init( &m_vd, &m_vi );
|
||||
vorbis_block_init( &m_vd, &m_vb );
|
||||
|
||||
// We give our ogg file a random serial number and avoid
|
||||
// 0 and UINT32_MAX which can get you into trouble.
|
||||
qsrand( time( 0 ) );
|
||||
m_serialNo = 0xD0000000 + qrand() % 0x0FFFFFFF;
|
||||
ogg_stream_init( &m_os, m_serialNo );
|
||||
|
||||
// Now, build the three header packets and send through to the stream
|
||||
|
||||
@@ -79,7 +79,12 @@ bool AudioFileWave::startEncoding()
|
||||
outputFile().toUtf8().constData(),
|
||||
#endif
|
||||
SFM_WRITE, &m_si );
|
||||
|
||||
// Prevent fold overs when encountering clipped data
|
||||
sf_command(m_sf, SFC_SET_CLIPPING, NULL, SF_TRUE);
|
||||
|
||||
sf_set_string ( m_sf, SF_STR_SOFTWARE, "LMMS" );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -160,7 +160,7 @@ int calc13octaveband31(float *absspec_buffer, float *subbands, int num_spec, flo
|
||||
{
|
||||
static const int onethirdoctavecenterfr[] = {20, 25, 31, 40, 50, 63, 80, 100, 125, 160, 200, 250, 315, 400, 500, 630, 800, 1000, 1250, 1600, 2000, 2500, 3150, 4000, 5000, 6300, 8000, 10000, 12500, 16000, 20000};
|
||||
int i, j;
|
||||
float f_min, f_max, frequency, bandwith;
|
||||
float f_min, f_max, frequency, bandwidth;
|
||||
int j_min, j_max=0;
|
||||
float fpower;
|
||||
|
||||
@@ -189,13 +189,13 @@ static const int onethirdoctavecenterfr[] = {20, 25, 31, 40, 50, 63, 80, 100, 12
|
||||
{
|
||||
subbands[i]=0;
|
||||
|
||||
// calculate bandwith for subband
|
||||
// calculate bandwidth for subband
|
||||
frequency=onethirdoctavecenterfr[i];
|
||||
|
||||
bandwith=(pow(2, 1.0/3.0)-1)*frequency;
|
||||
bandwidth=(pow(2, 1.0/3.0)-1)*frequency;
|
||||
|
||||
f_min=frequency-bandwith/2.0;
|
||||
f_max=frequency+bandwith/2.0;
|
||||
f_min=frequency-bandwidth/2.0;
|
||||
f_max=frequency+bandwidth/2.0;
|
||||
|
||||
j_min=(int)(f_min/max_frequency*(float)num_spec);
|
||||
|
||||
|
||||
@@ -151,6 +151,7 @@ void printHelp()
|
||||
" [ -i <method> ]\n"
|
||||
" [ --import <in> [-e]]\n"
|
||||
" [ -l ]\n"
|
||||
" [ -m <mode>]\n"
|
||||
" [ -o <path> ]\n"
|
||||
" [ -p <out> ]\n"
|
||||
" [ -r <project file> ] [ options ]\n"
|
||||
@@ -165,7 +166,7 @@ void printHelp()
|
||||
"-c, --config <configfile> Get the configuration from <configfile>\n"
|
||||
"-d, --dump <in> Dump XML of compressed file <in>\n"
|
||||
"-f, --format <format> Specify format of render-output where\n"
|
||||
" Format is either 'wav' or 'ogg'.\n"
|
||||
" Format is either 'wav', 'ogg' or 'mp3'.\n"
|
||||
" --geometry <geometry> Specify the size and position of the main window\n"
|
||||
" geometry is <xsizexysize+xoffset+yoffsety>.\n"
|
||||
"-h, --help Show this usage information and exit.\n"
|
||||
@@ -178,6 +179,12 @@ void printHelp()
|
||||
" --import <in> [-e] Import MIDI file <in>.\n"
|
||||
" If -e is specified lmms exits after importing the file.\n"
|
||||
"-l, --loop Render as a loop\n"
|
||||
"-m, --mode Stereo mode used for MP3 export\n"
|
||||
" Possible values: s, j, m\n"
|
||||
" s: Stereo\n"
|
||||
" j: Joint Stereo\n"
|
||||
" m: Mono\n"
|
||||
" Default: j\n"
|
||||
"-o, --output <path> Render into <path>\n"
|
||||
" For --render, provide a file path\n"
|
||||
" For --rendertracks, provide a directory path\n"
|
||||
@@ -291,7 +298,7 @@ int main( int argc, char * * argv )
|
||||
{
|
||||
printf( "LMMS cannot be run as root.\nUse \"--allowroot\" to override.\n\n" );
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
QCoreApplication * app = coreOnly ?
|
||||
@@ -299,7 +306,7 @@ int main( int argc, char * * argv )
|
||||
new MainApplication( argc, argv );
|
||||
|
||||
Mixer::qualitySettings qs( Mixer::qualitySettings::Mode_HighQuality );
|
||||
OutputSettings os( 44100, OutputSettings::BitRateSettings(160, false), OutputSettings::Depth_16Bit );
|
||||
OutputSettings os( 44100, OutputSettings::BitRateSettings(160, false), OutputSettings::Depth_16Bit, OutputSettings::StereoMode_JointStereo );
|
||||
ProjectRenderer::ExportFileFormats eff = ProjectRenderer::WaveFile;
|
||||
|
||||
// second of two command-line parsing stages
|
||||
@@ -353,7 +360,7 @@ int main( int argc, char * * argv )
|
||||
printf( "\nOption \"--allowroot\" will be ignored on this platform.\n\n" );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
else if( arg == "--dump" || arg == "-d" )
|
||||
{
|
||||
@@ -430,6 +437,12 @@ int main( int argc, char * * argv )
|
||||
{
|
||||
eff = ProjectRenderer::OggFile;
|
||||
}
|
||||
#endif
|
||||
#ifdef LMMS_HAVE_MP3LAME
|
||||
else if( ext == "mp3" )
|
||||
{
|
||||
eff = ProjectRenderer::MP3File;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
@@ -485,6 +498,38 @@ int main( int argc, char * * argv )
|
||||
else
|
||||
{
|
||||
printf( "\nInvalid bitrate %s.\n\n"
|
||||
"Try \"%s --help\" for more information.\n\n", argv[i], argv[0] );
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
else if( arg == "--mode" || arg == "-m" )
|
||||
{
|
||||
++i;
|
||||
|
||||
if( i == argc )
|
||||
{
|
||||
printf( "\nNo stereo mode specified.\n\n"
|
||||
"Try \"%s --help\" for more information.\n\n", argv[0] );
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
QString const mode( argv[i] );
|
||||
|
||||
if( mode == "s" )
|
||||
{
|
||||
os.setStereoMode(OutputSettings::StereoMode_Stereo);
|
||||
}
|
||||
else if( mode == "j" )
|
||||
{
|
||||
os.setStereoMode(OutputSettings::StereoMode_JointStereo);
|
||||
}
|
||||
else if( mode == "m" )
|
||||
{
|
||||
os.setStereoMode(OutputSettings::StereoMode_Mono);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf( "\nInvalid stereo mode %s.\n\n"
|
||||
"Try \"%s --help\" for more information.\n\n", argv[i], argv[0] );
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
@@ -778,10 +823,6 @@ int main( int argc, char * * argv )
|
||||
" <td><b>%4</b></td>"
|
||||
" <td>%5</td>"
|
||||
" </tr>"
|
||||
" <tr>"
|
||||
" <td><b>%6</b></td>"
|
||||
" <td>%7</td>"
|
||||
" </tr>"
|
||||
"</table>"
|
||||
"</html>" ).arg(
|
||||
MainWindow::tr( "There is a recovery file present. "
|
||||
@@ -792,10 +833,6 @@ int main( int argc, char * * argv )
|
||||
MainWindow::tr( "Recover" ),
|
||||
MainWindow::tr( "Recover the file. Please don't run "
|
||||
"multiple instances of LMMS when you do this." ),
|
||||
MainWindow::tr( "Ignore" ),
|
||||
MainWindow::tr( "Launch LMMS as usual but with "
|
||||
"automatic backup disabled to prevent the "
|
||||
"present recover file from being overwritten." ),
|
||||
MainWindow::tr( "Discard" ),
|
||||
MainWindow::tr( "Launch a default session and delete "
|
||||
"the restored files. This is not reversible." )
|
||||
@@ -807,38 +844,32 @@ int main( int argc, char * * argv )
|
||||
|
||||
QPushButton * recover;
|
||||
QPushButton * discard;
|
||||
QPushButton * ignore;
|
||||
QPushButton * exit;
|
||||
|
||||
|
||||
#if QT_VERSION >= 0x050000
|
||||
// setting all buttons to the same roles allows us
|
||||
// setting all buttons to the same roles allows us
|
||||
// to have a custom layout
|
||||
discard = mb.addButton( MainWindow::tr( "Discard" ),
|
||||
QMessageBox::AcceptRole );
|
||||
ignore = mb.addButton( MainWindow::tr( "Ignore" ),
|
||||
QMessageBox::AcceptRole );
|
||||
recover = mb.addButton( MainWindow::tr( "Recover" ),
|
||||
QMessageBox::AcceptRole );
|
||||
|
||||
# else
|
||||
# else
|
||||
// in qt4 the button order is reversed
|
||||
recover = mb.addButton( MainWindow::tr( "Recover" ),
|
||||
QMessageBox::AcceptRole );
|
||||
ignore = mb.addButton( MainWindow::tr( "Ignore" ),
|
||||
QMessageBox::AcceptRole );
|
||||
discard = mb.addButton( MainWindow::tr( "Discard" ),
|
||||
QMessageBox::AcceptRole );
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// have a hidden exit button
|
||||
exit = mb.addButton( "", QMessageBox::RejectRole);
|
||||
exit->setVisible(false);
|
||||
|
||||
|
||||
// set icons
|
||||
recover->setIcon( embed::getIconPixmap( "recover" ) );
|
||||
discard->setIcon( embed::getIconPixmap( "discard" ) );
|
||||
ignore->setIcon( embed::getIconPixmap( "ignore" ) );
|
||||
|
||||
mb.setDefaultButton( recover );
|
||||
mb.setEscapeButton( exit );
|
||||
@@ -853,13 +884,6 @@ int main( int argc, char * * argv )
|
||||
fileToLoad = recoveryFile;
|
||||
gui->mainWindow()->setSession( MainWindow::SessionState::Recover );
|
||||
}
|
||||
else if( mb.clickedButton() == ignore )
|
||||
{
|
||||
if( autoSaveEnabled )
|
||||
{
|
||||
gui->mainWindow()->setSession( MainWindow::SessionState::Limited );
|
||||
}
|
||||
}
|
||||
else // Exit
|
||||
{
|
||||
return 0;
|
||||
@@ -902,20 +926,19 @@ int main( int argc, char * * argv )
|
||||
}
|
||||
}
|
||||
// If enabled, open last project if there is one. Else, create
|
||||
// a new one. Also skip recently opened file if limited session to
|
||||
// lower the chance of opening an already opened file.
|
||||
// a new one.
|
||||
else if( ConfigManager::inst()->
|
||||
value( "app", "openlastproject" ).toInt() &&
|
||||
!ConfigManager::inst()->
|
||||
recentlyOpenedProjects().isEmpty() &&
|
||||
gui->mainWindow()->getSession() !=
|
||||
MainWindow::SessionState::Limited )
|
||||
!recoveryFilePresent )
|
||||
{
|
||||
QString f = ConfigManager::inst()->
|
||||
recentlyOpenedProjects().first();
|
||||
QFileInfo recentFile( f );
|
||||
|
||||
if ( recentFile.exists() )
|
||||
if ( recentFile.exists() &&
|
||||
recentFile.suffix().toLower() != "mpt" )
|
||||
{
|
||||
Engine::getSong()->loadProject( f );
|
||||
}
|
||||
@@ -932,8 +955,7 @@ int main( int argc, char * * argv )
|
||||
// Finally we start the auto save timer and also trigger the
|
||||
// autosave one time as recover.mmp is a signal to possible other
|
||||
// instances of LMMS.
|
||||
if( autoSaveEnabled &&
|
||||
gui->mainWindow()->getSession() != MainWindow::SessionState::Limited )
|
||||
if( autoSaveEnabled )
|
||||
{
|
||||
gui->mainWindow()->autoSaveTimerReset();
|
||||
gui->mainWindow()->autoSave();
|
||||
|
||||
@@ -67,6 +67,11 @@ void MidiClient::addPort( MidiPort* port )
|
||||
|
||||
void MidiClient::removePort( MidiPort* port )
|
||||
{
|
||||
if( ! port )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QVector<MidiPort *>::Iterator it =
|
||||
qFind( m_midiPorts.begin(), m_midiPorts.end(), port );
|
||||
if( it != m_midiPorts.end() )
|
||||
|
||||
@@ -129,11 +129,11 @@ void MidiPort::processInEvent( const MidiEvent& event, const MidiTime& time )
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if( fixedInputVelocity() >= 0 && inEvent.velocity() > 0 )
|
||||
{
|
||||
inEvent.setVelocity( fixedInputVelocity() );
|
||||
if( fixedInputVelocity() >= 0 && inEvent.velocity() > 0 )
|
||||
{
|
||||
inEvent.setVelocity( fixedInputVelocity() );
|
||||
}
|
||||
}
|
||||
|
||||
m_midiEventProcessor->processInEvent( inEvent, time );
|
||||
|
||||
@@ -85,6 +85,7 @@ SET(LMMS_SRCS
|
||||
gui/widgets/ToolButton.cpp
|
||||
gui/widgets/ToolTip.cpp
|
||||
gui/widgets/TrackLabelButton.cpp
|
||||
gui/widgets/TrackRenameLineEdit.cpp
|
||||
gui/widgets/VisualizationWidget.cpp
|
||||
|
||||
PARENT_SCOPE
|
||||
|
||||
@@ -58,7 +58,7 @@ ExportProjectDialog::ExportProjectDialog( const QString & _file_name,
|
||||
int cbIndex = 0;
|
||||
for( int i = 0; i < ProjectRenderer::NumFileFormats; ++i )
|
||||
{
|
||||
if( ProjectRenderer::fileEncodeDevices[i].m_getDevInst != NULL )
|
||||
if( ProjectRenderer::fileEncodeDevices[i].isAvailable() )
|
||||
{
|
||||
// get the extension of this format
|
||||
QString renderExt = ProjectRenderer::fileEncodeDevices[i].m_extension;
|
||||
@@ -128,7 +128,20 @@ void ExportProjectDialog::closeEvent( QCloseEvent * _ce )
|
||||
}
|
||||
|
||||
|
||||
|
||||
OutputSettings::StereoMode mapToStereoMode(int index)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
return OutputSettings::StereoMode_Stereo;
|
||||
case 1:
|
||||
return OutputSettings::StereoMode_JointStereo;
|
||||
case 2:
|
||||
return OutputSettings::StereoMode_Mono;
|
||||
default:
|
||||
return OutputSettings::StereoMode_Stereo;
|
||||
}
|
||||
}
|
||||
|
||||
void ExportProjectDialog::startExport()
|
||||
{
|
||||
@@ -146,7 +159,8 @@ void ExportProjectDialog::startExport()
|
||||
OutputSettings os = OutputSettings(
|
||||
samplerates[ samplerateCB->currentIndex() ],
|
||||
bitRateSettings,
|
||||
static_cast<OutputSettings::BitDepth>( depthCB->currentIndex() ) );
|
||||
static_cast<OutputSettings::BitDepth>( depthCB->currentIndex() ),
|
||||
mapToStereoMode(stereoModeComboBox->currentIndex()) );
|
||||
|
||||
m_renderManager = new RenderManager( qs, os, m_ft, m_fileName );
|
||||
|
||||
@@ -181,6 +195,8 @@ ProjectRenderer::ExportFileFormats convertIndexToExportFileFormat(int index)
|
||||
return ProjectRenderer::WaveFile;
|
||||
case 1:
|
||||
return ProjectRenderer::OggFile;
|
||||
case 2:
|
||||
return ProjectRenderer::MP3File;
|
||||
default:
|
||||
Q_ASSERT(false);
|
||||
break;
|
||||
@@ -195,10 +211,23 @@ void ExportProjectDialog::onFileFormatChanged(int index)
|
||||
ProjectRenderer::ExportFileFormats exportFormat =
|
||||
convertIndexToExportFileFormat(index);
|
||||
|
||||
bool bitRateControlsEnabled = exportFormat == ProjectRenderer::OggFile;
|
||||
bool stereoModeVisible = exportFormat == ProjectRenderer::MP3File;
|
||||
|
||||
bool sampleRateControlsVisible = exportFormat != ProjectRenderer::MP3File;
|
||||
|
||||
bool bitRateControlsEnabled =
|
||||
(exportFormat == ProjectRenderer::OggFile ||
|
||||
exportFormat == ProjectRenderer::MP3File);
|
||||
|
||||
bool bitDepthControlEnabled = exportFormat == ProjectRenderer::WaveFile;
|
||||
|
||||
bool variableBitrateVisible = exportFormat != ProjectRenderer::MP3File;
|
||||
|
||||
stereoModeWidget->setVisible(stereoModeVisible);
|
||||
sampleRateWidget->setVisible(sampleRateControlsVisible);
|
||||
|
||||
bitrateWidget->setVisible(bitRateControlsEnabled);
|
||||
checkBoxVariableBitRate->setVisible(variableBitrateVisible);
|
||||
|
||||
depthWidget->setVisible(bitDepthControlEnabled);
|
||||
}
|
||||
|
||||
@@ -664,10 +664,6 @@ void MainWindow::resetWindowTitle()
|
||||
{
|
||||
title += " - " + tr( "Recover session. Please save your work!" );
|
||||
}
|
||||
if( getSession() == Limited )
|
||||
{
|
||||
title += " - " + tr( "Automatic backup disabled. Remember to save your work!" );
|
||||
}
|
||||
setWindowTitle( title + " - " + tr( "LMMS %1" ).arg( LMMS_VERSION ) );
|
||||
}
|
||||
|
||||
@@ -738,7 +734,7 @@ void MainWindow::clearKeyModifiers()
|
||||
|
||||
|
||||
|
||||
void MainWindow::saveWidgetState( QWidget * _w, QDomElement & _de, QSize const & sizeIfInvisible )
|
||||
void MainWindow::saveWidgetState( QWidget * _w, QDomElement & _de )
|
||||
{
|
||||
// If our widget is the main content of a window (e.g. piano roll, FxMixer, etc),
|
||||
// we really care about the position of the *window* - not the position of the widget within its window
|
||||
@@ -761,7 +757,7 @@ void MainWindow::saveWidgetState( QWidget * _w, QDomElement & _de, QSize const &
|
||||
_de.setAttribute( "x", normalGeom.x() );
|
||||
_de.setAttribute( "y", normalGeom.y() );
|
||||
|
||||
QSize sizeToStore = visible ? normalGeom.size() : sizeIfInvisible;
|
||||
QSize sizeToStore = normalGeom.size();
|
||||
_de.setAttribute( "width", sizeToStore.width() );
|
||||
_de.setAttribute( "height", sizeToStore.height() );
|
||||
}
|
||||
@@ -773,8 +769,8 @@ void MainWindow::restoreWidgetState( QWidget * _w, const QDomElement & _de )
|
||||
{
|
||||
QRect r( qMax( 1, _de.attribute( "x" ).toInt() ),
|
||||
qMax( 1, _de.attribute( "y" ).toInt() ),
|
||||
qMax( 100, _de.attribute( "width" ).toInt() ),
|
||||
qMax( 100, _de.attribute( "height" ).toInt() ) );
|
||||
qMax( _w->sizeHint().width(), _de.attribute( "width" ).toInt() ),
|
||||
qMax( _w->minimumHeight(), _de.attribute( "height" ).toInt() ) );
|
||||
if( _de.hasAttribute( "visible" ) && !r.isNull() )
|
||||
{
|
||||
// If our widget is the main content of a window (e.g. piano roll, FxMixer, etc),
|
||||
@@ -880,8 +876,8 @@ void MainWindow::updateRecentlyOpenedProjectsMenu()
|
||||
m_recentlyOpenedProjectsMenu->clear();
|
||||
QStringList rup = ConfigManager::inst()->recentlyOpenedProjects();
|
||||
|
||||
// The file history goes 30 deep but we only show the 15
|
||||
// most recent ones that we can open.
|
||||
// The file history goes 50 deep but we only show the 15
|
||||
// most recent ones that we can open and omit .mpt files.
|
||||
int shownInMenu = 0;
|
||||
for( QStringList::iterator it = rup.begin(); it != rup.end(); ++it )
|
||||
{
|
||||
@@ -889,6 +885,11 @@ void MainWindow::updateRecentlyOpenedProjectsMenu()
|
||||
if ( recentFile.exists() &&
|
||||
*it != ConfigManager::inst()->recoveryFile() )
|
||||
{
|
||||
if( recentFile.suffix().toLower() == "mpt" )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
m_recentlyOpenedProjectsMenu->addAction(
|
||||
embed::getIconPixmap( "project_file" ), *it );
|
||||
#ifdef LMMS_BUILD_APPLE
|
||||
@@ -1374,8 +1375,8 @@ void MainWindow::closeEvent( QCloseEvent * _ce )
|
||||
if( mayChangeProject(true) )
|
||||
{
|
||||
// delete recovery file
|
||||
if( ConfigManager::inst()->value( "ui", "enableautosave" ).toInt()
|
||||
&& getSession() != Limited )
|
||||
if( ConfigManager::inst()->
|
||||
value( "ui", "enableautosave" ).toInt() )
|
||||
{
|
||||
sessionCleanup();
|
||||
_ce->accept();
|
||||
@@ -1562,8 +1563,7 @@ void MainWindow::autoSave()
|
||||
// from the timer where we need to do extra tests.
|
||||
void MainWindow::runAutoSave()
|
||||
{
|
||||
if( ConfigManager::inst()->value( "ui", "enableautosave" ).toInt() &&
|
||||
getSession() != Limited )
|
||||
if( ConfigManager::inst()->value( "ui", "enableautosave" ).toInt() )
|
||||
{
|
||||
autoSave();
|
||||
autoSaveTimerReset(); // Reset timer
|
||||
|
||||
@@ -119,8 +119,8 @@ SetupDialog::SetupDialog( ConfigTabs _tab_to_open ) :
|
||||
#endif
|
||||
m_backgroundArtwork( QDir::toNativeSeparators( ConfigManager::inst()->backgroundArtwork() ) ),
|
||||
m_smoothScroll( ConfigManager::inst()->value( "ui", "smoothscroll" ).toInt() ),
|
||||
m_enableAutoSave( ConfigManager::inst()->value( "ui", "enableautosave" ).toInt() ),
|
||||
m_enableRunningAutoSave( ConfigManager::inst()->value( "ui", "enablerunningautosave" ).toInt() ),
|
||||
m_enableAutoSave( ConfigManager::inst()->value( "ui", "enableautosave", "1" ).toInt() ),
|
||||
m_enableRunningAutoSave( ConfigManager::inst()->value( "ui", "enablerunningautosave", "1" ).toInt() ),
|
||||
m_saveInterval( ConfigManager::inst()->value( "ui", "saveinterval" ).toInt() < 1 ?
|
||||
MainWindow::DEFAULT_SAVE_INTERVAL_MINUTES :
|
||||
ConfigManager::inst()->value( "ui", "saveinterval" ).toInt() ),
|
||||
@@ -131,7 +131,7 @@ SetupDialog::SetupDialog( ConfigTabs _tab_to_open ) :
|
||||
m_syncVSTPlugins( ConfigManager::inst()->value( "ui",
|
||||
"syncvstplugins" ).toInt() ),
|
||||
m_animateAFP(ConfigManager::inst()->value( "ui",
|
||||
"animateafp").toInt() ),
|
||||
"animateafp", "1" ).toInt() ),
|
||||
m_printNoteLabels(ConfigManager::inst()->value( "ui",
|
||||
"printnotelabels").toInt() ),
|
||||
m_displayWaveform(ConfigManager::inst()->value( "ui",
|
||||
|
||||
@@ -94,6 +94,8 @@ TimeLineWidget::TimeLineWidget( const int xoff, const int yoff, const float ppt,
|
||||
connect( updateTimer, SIGNAL( timeout() ),
|
||||
this, SLOT( updatePosition() ) );
|
||||
updateTimer->start( 50 );
|
||||
connect( Engine::getSong(), SIGNAL( timeSignatureChanged( int,int ) ),
|
||||
this, SLOT( update() ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>715</width>
|
||||
<height>447</height>
|
||||
<height>491</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
@@ -45,39 +45,48 @@
|
||||
<widget class="QComboBox" name="fileFormatCB"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Samplerate:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="samplerateCB">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>44100 Hz</string>
|
||||
<widget class="QWidget" name="sampleRateWidget" native="true">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>48000 Hz</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>88200 Hz</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>96000 Hz</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>192000 Hz</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelSampleRate">
|
||||
<property name="text">
|
||||
<string>Samplerate:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="samplerateCB">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>44100 Hz</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>48000 Hz</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>88200 Hz</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>96000 Hz</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>192000 Hz</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@@ -124,6 +133,44 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="stereoModeWidget" native="true">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelStereoMode_3">
|
||||
<property name="text">
|
||||
<string>Stereo mode:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="stereoModeComboBox">
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Stereo</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Joint Stereo</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Mono</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="bitrateWidget" native="true">
|
||||
<layout class="QVBoxLayout">
|
||||
|
||||
@@ -69,7 +69,7 @@ QPixmap * AutomationEditor::s_toolYFlip = NULL;
|
||||
QPixmap * AutomationEditor::s_toolXFlip = NULL;
|
||||
|
||||
const QVector<double> AutomationEditor::m_zoomXLevels =
|
||||
{ 8.0f, 4.0f, 2.0f, 1.0f, 0.5f, 0.25f, 0.125f };
|
||||
{ 0.125f, 0.25f, 0.5f, 1.0f, 2.0f, 4.0f, 8.0f };
|
||||
|
||||
|
||||
|
||||
@@ -239,7 +239,7 @@ void AutomationEditor::setCurrentPattern(AutomationPattern * new_pattern )
|
||||
|
||||
void AutomationEditor::saveSettings(QDomDocument & doc, QDomElement & dom_parent)
|
||||
{
|
||||
MainWindow::saveWidgetState(parentWidget(), dom_parent, QSize( 640, 400 ));
|
||||
MainWindow::saveWidgetState( parentWidget(), dom_parent );
|
||||
}
|
||||
|
||||
|
||||
@@ -1233,18 +1233,20 @@ void AutomationEditor::paintEvent(QPaintEvent * pe )
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// alternating shades for better contrast
|
||||
// count the bars which disappear on left by scrolling
|
||||
|
||||
float timeSignature = static_cast<float>( Engine::getSong()->getTimeSigModel().getNumerator() )
|
||||
/ static_cast<float>( Engine::getSong()->getTimeSigModel().getDenominator() );
|
||||
float zoomFactor = m_zoomXLevels[m_zoomingXModel.value()];
|
||||
int barCount = m_currentPosition / MidiTime::ticksPerTact();
|
||||
int leftBars = m_currentPosition * zoomFactor / m_ppt;
|
||||
//the bars which disappears at the left side by scrolling
|
||||
int leftBars = m_currentPosition * zoomFactor / MidiTime::ticksPerTact();
|
||||
|
||||
for( int x = VALUES_WIDTH; x < width() + m_currentPosition * zoomFactor; x += m_ppt, ++barCount )
|
||||
//iterates the visible bars and draw the shading on uneven bars
|
||||
for( int x = VALUES_WIDTH, barCount = leftBars; x < width() + m_currentPosition * zoomFactor / timeSignature; x += m_ppt, ++barCount )
|
||||
{
|
||||
if( ( barCount + leftBars ) % 2 != 0 )
|
||||
{
|
||||
p.fillRect( x - m_currentPosition * zoomFactor, TOP_MARGIN, m_ppt,
|
||||
p.fillRect( x - m_currentPosition * zoomFactor / timeSignature, TOP_MARGIN, m_ppt,
|
||||
height() - ( SCROLLBAR_SIZE + TOP_MARGIN ), backgroundShade() );
|
||||
}
|
||||
}
|
||||
@@ -1301,7 +1303,7 @@ void AutomationEditor::paintEvent(QPaintEvent * pe )
|
||||
//Don't bother doing/rendering anything if there is no automation points
|
||||
if( time_map.size() > 0 )
|
||||
{
|
||||
timeMap::iterator it = time_map.begin();
|
||||
timeMap::iterator it = time_map.begin();
|
||||
while( it+1 != time_map.end() )
|
||||
{
|
||||
// skip this section if it occurs completely before the
|
||||
@@ -1318,7 +1320,7 @@ void AutomationEditor::paintEvent(QPaintEvent * pe )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
//NEEDS Change in CSS
|
||||
/*bool is_selected = false;
|
||||
// if we're in move-mode, we may only draw
|
||||
@@ -1358,8 +1360,8 @@ void AutomationEditor::paintEvent(QPaintEvent * pe )
|
||||
for( int i = 0; i < ( it + 1 ).key() - it.key(); i++ )
|
||||
{ path.lineTo( QPointF( xCoordOfTick( it.key() + i ), yCoordOfLevel( values[i] ) ) );
|
||||
//NEEDS Change in CSS
|
||||
//drawLevelTick( p, it.key() + i, values[i], is_selected );
|
||||
|
||||
//drawLevelTick( p, it.key() + i, values[i], is_selected );
|
||||
|
||||
}
|
||||
path.lineTo( QPointF( xCoordOfTick( ( it + 1 ).key() ), yCoordOfLevel( nextValue ) ) );
|
||||
path.lineTo( QPointF( xCoordOfTick( ( it + 1 ).key() ), yCoordOfLevel( 0 ) ) );
|
||||
@@ -1535,12 +1537,12 @@ void AutomationEditor::drawLevelTick(QPainter & p, int tick, float value)
|
||||
|
||||
p.fillRect( x, y_start, rect_width, rect_height, currentColor );
|
||||
}
|
||||
|
||||
|
||||
else
|
||||
{
|
||||
printf("not in range\n");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1598,12 +1600,12 @@ void AutomationEditor::wheelEvent(QWheelEvent * we )
|
||||
{
|
||||
y++;
|
||||
}
|
||||
if( we->delta() < 0 )
|
||||
else if( we->delta() < 0 )
|
||||
{
|
||||
y--;
|
||||
}
|
||||
y = qBound( 0, y, m_zoomingYModel.size() - 1 );
|
||||
m_zoomingYModel.setValue( y );
|
||||
m_zoomingYModel.setValue( y );
|
||||
}
|
||||
else if( we->modifiers() & Qt::ControlModifier && we->modifiers() & Qt::AltModifier )
|
||||
{
|
||||
@@ -1612,7 +1614,7 @@ void AutomationEditor::wheelEvent(QWheelEvent * we )
|
||||
{
|
||||
q--;
|
||||
}
|
||||
if( we->delta() < 0 )
|
||||
else if( we->delta() < 0 )
|
||||
{
|
||||
q++;
|
||||
}
|
||||
@@ -1624,13 +1626,13 @@ void AutomationEditor::wheelEvent(QWheelEvent * we )
|
||||
{
|
||||
int x = m_zoomingXModel.value();
|
||||
if( we->delta() > 0 )
|
||||
{
|
||||
x--;
|
||||
}
|
||||
if( we->delta() < 0 )
|
||||
{
|
||||
x++;
|
||||
}
|
||||
else if( we->delta() < 0 )
|
||||
{
|
||||
x--;
|
||||
}
|
||||
x = qBound( 0, x, m_zoomingXModel.size() - 1 );
|
||||
m_zoomingXModel.setValue( x );
|
||||
}
|
||||
|
||||
@@ -237,7 +237,7 @@ void BBTrackContainerView::removeBBView(int bb)
|
||||
|
||||
void BBTrackContainerView::saveSettings(QDomDocument& doc, QDomElement& element)
|
||||
{
|
||||
MainWindow::saveWidgetState(parentWidget(), element, QSize( 640, 400 ) );
|
||||
MainWindow::saveWidgetState( parentWidget(), element );
|
||||
}
|
||||
|
||||
void BBTrackContainerView::loadSettings(const QDomElement& element)
|
||||
|
||||
@@ -143,7 +143,7 @@ PianoRoll::PianoRollKeyTypes PianoRoll::prKeyOrder[] =
|
||||
const int DEFAULT_PR_PPT = KEY_LINE_HEIGHT * DefaultStepsPerTact;
|
||||
|
||||
const QVector<double> PianoRoll::m_zoomLevels =
|
||||
{ 8.0f, 4.0f, 2.0f, 1.0f, 0.5f, 0.25f, 0.125f };
|
||||
{ 0.125f, 0.25f, 0.5f, 1.0f, 2.0f, 4.0f, 8.0f };
|
||||
|
||||
|
||||
PianoRoll::PianoRoll() :
|
||||
@@ -805,7 +805,7 @@ void PianoRoll::setBackgroundShade( const QColor & c )
|
||||
|
||||
|
||||
|
||||
void PianoRoll::drawNoteRect( QPainter & p, int x, int y,
|
||||
void PianoRoll::drawNoteRect( QPainter & p, int x, int y,
|
||||
int width, const Note * n, const QColor & noteCol,
|
||||
const QColor & selCol, const int noteOpc, const bool borders )
|
||||
{
|
||||
@@ -997,6 +997,7 @@ void PianoRoll::shiftPos( int amount ) //shift notes pos by amount
|
||||
}
|
||||
|
||||
m_pattern->rearrangeAllNotes();
|
||||
m_pattern->updateLength();
|
||||
m_pattern->dataChanged();
|
||||
|
||||
// we modified the song
|
||||
@@ -1917,7 +1918,7 @@ void PianoRoll::mouseReleaseEvent( QMouseEvent * me )
|
||||
{
|
||||
// select the notes within the selection rectangle and
|
||||
// then destroy the selection rectangle
|
||||
computeSelectedNotes(
|
||||
computeSelectedNotes(
|
||||
me->modifiers() & Qt::ShiftModifier );
|
||||
}
|
||||
else if( m_action == ActionMoveNote )
|
||||
@@ -2459,15 +2460,10 @@ void PianoRoll::dragNotes( int x, int y, bool alt, bool shift, bool ctrl )
|
||||
|
||||
note->setPos( MidiTime( pos_ticks ) );
|
||||
note->setKey( key_num );
|
||||
// If dragging beat notes check if pattern should be MelodyPattern
|
||||
if( note->length() < 0 )
|
||||
{
|
||||
m_pattern->checkType();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (m_action == ActionResizeNote)
|
||||
{
|
||||
// When resizing notes:
|
||||
@@ -2475,7 +2471,7 @@ void PianoRoll::dragNotes( int x, int y, bool alt, bool shift, bool ctrl )
|
||||
// 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 (shift)
|
||||
{
|
||||
// Algorithm:
|
||||
@@ -2495,8 +2491,8 @@ void PianoRoll::dragNotes( int x, int y, bool alt, bool shift, bool ctrl )
|
||||
const Note *posteriorNote = nullptr;
|
||||
for (const Note *note : notes)
|
||||
{
|
||||
if (note->selected() && (posteriorNote == nullptr ||
|
||||
note->oldPos().getTicks() + note->oldLength().getTicks() >
|
||||
if (note->selected() && (posteriorNote == nullptr ||
|
||||
note->oldPos().getTicks() + note->oldLength().getTicks() >
|
||||
posteriorNote->oldPos().getTicks() + posteriorNote->oldLength().getTicks()))
|
||||
{
|
||||
posteriorNote = note;
|
||||
@@ -2516,9 +2512,9 @@ void PianoRoll::dragNotes( int x, int y, bool alt, bool shift, bool ctrl )
|
||||
if(note->selected())
|
||||
{
|
||||
// scale relative start and end positions by scaleFactor
|
||||
int newStart = stretchStartTick + scaleFactor *
|
||||
int newStart = stretchStartTick + scaleFactor *
|
||||
(note->oldPos().getTicks() - stretchStartTick);
|
||||
int newEnd = stretchStartTick + scaleFactor *
|
||||
int newEnd = stretchStartTick + scaleFactor *
|
||||
(note->oldPos().getTicks()+note->oldLength().getTicks() - stretchStartTick);
|
||||
// if not holding alt, quantize the offsets
|
||||
if(!alt)
|
||||
@@ -2537,7 +2533,7 @@ void PianoRoll::dragNotes( int x, int y, bool alt, bool shift, bool ctrl )
|
||||
int newLength = qMax(1, newEnd-newStart);
|
||||
if (note == posteriorNote)
|
||||
{
|
||||
posteriorDeltaThisFrame = (newStart+newLength) -
|
||||
posteriorDeltaThisFrame = (newStart+newLength) -
|
||||
(note->pos().getTicks() + note->length().getTicks());
|
||||
}
|
||||
note->setLength( MidiTime(newLength) );
|
||||
@@ -2892,18 +2888,20 @@ void PianoRoll::paintEvent(QPaintEvent * pe )
|
||||
++key;
|
||||
}
|
||||
|
||||
|
||||
// Draw alternating shades on bars
|
||||
// count the bars which disappear on left by scrolling
|
||||
|
||||
float timeSignature = static_cast<float>( Engine::getSong()->getTimeSigModel().getNumerator() )
|
||||
/ static_cast<float>( Engine::getSong()->getTimeSigModel().getDenominator() );
|
||||
float zoomFactor = m_zoomLevels[m_zoomingModel.value()];
|
||||
int barCount = m_currentPosition / MidiTime::ticksPerTact();
|
||||
int leftBars = m_currentPosition * zoomFactor / m_ppt;
|
||||
//the bars which disappears at the left side by scrolling
|
||||
int leftBars = m_currentPosition * zoomFactor / MidiTime::ticksPerTact();
|
||||
|
||||
for( int x = WHITE_KEY_WIDTH; x < width() + m_currentPosition * zoomFactor; x += m_ppt, ++barCount )
|
||||
//iterates the visible bars and draw the shading on uneven bars
|
||||
for( int x = WHITE_KEY_WIDTH, barCount = leftBars; x < width() + m_currentPosition * zoomFactor / timeSignature; x += m_ppt, ++barCount )
|
||||
{
|
||||
if( ( barCount + leftBars ) % 2 != 0 )
|
||||
{
|
||||
p.fillRect( x - m_currentPosition * zoomFactor, PR_TOP_MARGIN, m_ppt,
|
||||
p.fillRect( x - m_currentPosition * zoomFactor / timeSignature, PR_TOP_MARGIN, m_ppt,
|
||||
height() - ( PR_BOTTOM_MARGIN + PR_TOP_MARGIN ), backgroundShade() );
|
||||
}
|
||||
}
|
||||
@@ -3258,7 +3256,7 @@ void PianoRoll::wheelEvent(QWheelEvent * we )
|
||||
{
|
||||
q--;
|
||||
}
|
||||
if( we->delta() < 0 )
|
||||
else if( we->delta() < 0 )
|
||||
{
|
||||
q++;
|
||||
}
|
||||
@@ -3272,7 +3270,7 @@ void PianoRoll::wheelEvent(QWheelEvent * we )
|
||||
{
|
||||
l--;
|
||||
}
|
||||
if( we->delta() < 0 )
|
||||
else if( we->delta() < 0 )
|
||||
{
|
||||
l++;
|
||||
}
|
||||
@@ -3283,13 +3281,13 @@ void PianoRoll::wheelEvent(QWheelEvent * we )
|
||||
{
|
||||
int z = m_zoomingModel.value();
|
||||
if( we->delta() > 0 )
|
||||
{
|
||||
z--;
|
||||
}
|
||||
if( we->delta() < 0 )
|
||||
{
|
||||
z++;
|
||||
}
|
||||
else if( we->delta() < 0 )
|
||||
{
|
||||
z--;
|
||||
}
|
||||
z = qBound( 0, z, m_zoomingModel.size() - 1 );
|
||||
// update combobox with zooming-factor
|
||||
m_zoomingModel.setValue( z );
|
||||
@@ -3920,27 +3918,32 @@ int PianoRoll::quantization() const
|
||||
|
||||
void PianoRoll::quantizeNotes()
|
||||
{
|
||||
if( ! hasValidPattern() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NoteVector notes = getSelectedNotes();
|
||||
|
||||
if (notes.empty())
|
||||
if( notes.empty() )
|
||||
{
|
||||
for (Note* n : m_pattern->notes())
|
||||
for( Note* n : m_pattern->notes() )
|
||||
{
|
||||
notes.push_back(n);
|
||||
notes.push_back( n );
|
||||
}
|
||||
}
|
||||
|
||||
for (Note* n : notes)
|
||||
for( Note* n : notes )
|
||||
{
|
||||
if (n->length() == MidiTime(0))
|
||||
if( n->length() == MidiTime( 0 ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Note copy(*n);
|
||||
m_pattern->removeNote(n);
|
||||
copy.quantizePos(quantization());
|
||||
m_pattern->addNote(copy);
|
||||
m_pattern->removeNote( n );
|
||||
copy.quantizePos( quantization() );
|
||||
m_pattern->addNote( copy );
|
||||
}
|
||||
|
||||
update();
|
||||
@@ -4389,7 +4392,7 @@ void PianoRollWindow::reset()
|
||||
|
||||
void PianoRollWindow::saveSettings( QDomDocument & doc, QDomElement & de )
|
||||
{
|
||||
MainWindow::saveWidgetState( this, de, QSize( 640, 480 ) );
|
||||
MainWindow::saveWidgetState( this, de );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ void positionLine::paintEvent( QPaintEvent * pe )
|
||||
}
|
||||
|
||||
const QVector<double> SongEditor::m_zoomLevels =
|
||||
{ 16.0f, 8.0f, 4.0f, 2.0f, 1.0f, 0.5f, 0.25f, 0.125f };
|
||||
{ 0.125f, 0.25f, 0.5f, 1.0f, 2.0f, 4.0f, 8.0f, 16.0f };
|
||||
|
||||
|
||||
SongEditor::SongEditor( Song * song ) :
|
||||
@@ -262,7 +262,7 @@ SongEditor::~SongEditor()
|
||||
|
||||
void SongEditor::saveSettings( QDomDocument& doc, QDomElement& element )
|
||||
{
|
||||
MainWindow::saveWidgetState(parentWidget(), element, QSize( 640, 400 ));
|
||||
MainWindow::saveWidgetState( parentWidget(), element );
|
||||
}
|
||||
|
||||
void SongEditor::loadSettings( const QDomElement& element )
|
||||
@@ -360,13 +360,13 @@ void SongEditor::wheelEvent( QWheelEvent * we )
|
||||
int z = m_zoomingModel->value();
|
||||
|
||||
if( we->delta() > 0 )
|
||||
{
|
||||
z--;
|
||||
}
|
||||
if( we->delta() < 0 )
|
||||
{
|
||||
z++;
|
||||
}
|
||||
else if( we->delta() < 0 )
|
||||
{
|
||||
z--;
|
||||
}
|
||||
z = qBound( 0, z, m_zoomingModel->size() - 1 );
|
||||
// update combobox with zooming-factor
|
||||
m_zoomingModel->setValue( z );
|
||||
@@ -586,6 +586,14 @@ void SongEditor::updatePosition( const MidiTime & t )
|
||||
|
||||
|
||||
|
||||
void SongEditor::updatePositionLine()
|
||||
{
|
||||
m_positionLine->setFixedHeight( height() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void SongEditor::zoomingChanged()
|
||||
{
|
||||
setPixelsPerTact( m_zoomLevels[m_zoomingModel->value()] * DEFAULT_PIXELS_PER_TACT );
|
||||
@@ -697,6 +705,7 @@ SongEditorWindow::SongEditorWindow(Song* song) :
|
||||
zoomToolBar->addWidget( m_zoomingComboBox );
|
||||
|
||||
connect(song, SIGNAL(projectLoaded()), this, SLOT(adjustUiAfterProjectLoad()));
|
||||
connect(this, SIGNAL(resized()), m_editor, SLOT(updatePositionLine()));
|
||||
}
|
||||
|
||||
QSize SongEditorWindow::sizeHint() const
|
||||
@@ -705,6 +714,14 @@ QSize SongEditorWindow::sizeHint() const
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void SongEditorWindow::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
emit resized();
|
||||
}
|
||||
|
||||
|
||||
void SongEditorWindow::play()
|
||||
{
|
||||
emit playTriggered();
|
||||
|
||||
@@ -102,7 +102,7 @@ ControllerRackView::~ControllerRackView()
|
||||
void ControllerRackView::saveSettings( QDomDocument & _doc,
|
||||
QDomElement & _this )
|
||||
{
|
||||
MainWindow::saveWidgetState( this, _this, QSize( 400, 300) );
|
||||
MainWindow::saveWidgetState( this, _this );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ EffectRackView::EffectRackView( EffectChain* model, QWidget* parent ) :
|
||||
ModelView( NULL, this )
|
||||
{
|
||||
QVBoxLayout* mainLayout = new QVBoxLayout( this );
|
||||
mainLayout->setMargin( 0 );
|
||||
mainLayout->setMargin( 5 );
|
||||
|
||||
m_effectsGroupBox = new GroupBox( tr( "EFFECTS CHAIN" ) );
|
||||
mainLayout->addWidget( m_effectsGroupBox );
|
||||
|
||||