Compare commits

...

126 Commits

Author SHA1 Message Date
Umcaruje
481cb2e889 Bump version to RC5 2017-12-19 18:24:15 +01:00
tresf
1279244e50 Add $HOME/bin to PATH
Circumvent change in appimagetool, per AppImage/AppImageKit#592
2017-12-18 18:55:51 -05:00
Lukas W
7c71bc657c Merge pull request #3786 from LMMS/fix/qt5-vst
Add all the Qt5 Linux VST implementations
2017-12-18 22:15:45 +01:00
Lukas W
19f48898a7 VST: Disable plugin reload on embed method change 2017-12-18 12:05:29 +01:00
Oskar Wallgren
76766c4c85 Piano Roll - Don't quantize when pasting notes (#4058)
Some changes on pasting notes in the Piano Roll:
* Don't quantize notes when pasting
* Add journal checkpoint
* Set project changed
2017-12-17 21:48:33 +01:00
Lukas W
5bad0ea8c0 Merge pull request #4046 from devnexen/build_fix
Few code fixes since we re dealing with C++11
2017-12-13 14:32:42 +01:00
Oskar Wallgren
54be88f536 Automation Editor - remove (comment out) unimplemented buttons (#4051) 2017-12-12 18:44:10 +01:00
tresf
5174bdaa0d Spaces to tabs 2017-12-11 10:46:19 -05:00
David Carlier
a653d01ac8 Few code fixes since we re dealing with C++11 2017-12-09 07:55:30 +00:00
Oskar Wallgren
06c40fc821 Automation Editor - Straighten out draw line function (#3997)
Fixes:
  AutomationEditor::drawLine(..) - quantize input
  AutomationEditor::drawLine(..) - Adjust line level.
2017-12-06 06:18:38 +01:00
Tres Finocchiaro
260c1843dd Fix typo from b6441b7
Closes #4039
2017-12-05 21:58:51 -05:00
Dan Williams
45d6b299ef Fix a crash (#4037)
This code loads a Qt5 library, which will cause problems if done from a Qt4 application. If the application is Qt4 based we don't have a bug with kde changing the menus anyway, so we can skip this code.
2017-12-05 21:36:54 -05:00
Hyunjin Song
dd4a73eb4b Fix various bugs when using JACK (#4005)
* Fix crash on closing
* Fix audio rendering artifacts
* Make LMMS work properly after rendering
2017-12-03 11:27:49 +09:00
Tres Finocchiaro
d711b8b55e Add Carla Support to AppImage (#4026)
Build AppImage with Carla support
* Disables HiDPI support in the AppImages
* Ignores deprecated jack usage
* Fix Carla compilation warnings
* Detects carla prefix in AppRun
2017-12-01 13:19:44 -05:00
Hyunjin Song
6cc118c259 Fix automation unit test for Qt4
Fixes failing Travis-CI build
2017-12-01 11:26:37 +09:00
Lukas W
d146308c02 Add more automation tests
See issue #3800 (Automations continue after the end of their TCOs) which
was fixed via #4012
2017-11-30 19:43:49 +01:00
Lukas W
ee9b593e26 Merge pull request #4012 from PhysSong/autoshrink
Handle shrank automation patterns correctly
2017-11-30 19:19:08 +01:00
Steffen Baranowsky
898e7999dc fixes bug when changing value by double click on fader/knob (#4018) 2017-11-30 16:57:15 +01:00
Lukas W
7ae348eb10 Vst refactorings 2017-11-29 15:33:44 +01:00
Lukas W
a446775c80 VST: Fix Qt-embedded VSTs not always appearing 2017-11-29 15:33:36 +01:00
Lukas W
ae488b89cd Fix VstEffect width issue 2017-11-29 14:44:53 +01:00
tresf
d0194e6c64 Bump Qt to 5.9.2
Closes #3925
2017-11-27 10:42:17 -05:00
Hyunin Song
72dcefc5f2 Handle shrinked automation patterns correctly 2017-11-26 21:04:06 +09:00
Lukas W
8c02495f27 Qt4 compat simplified 2017-11-25 15:25:32 +01:00
Lukas W
238d6b627c CMake: Fix RemoteVstPlugin build when winebuild is not in PATH 2017-11-25 14:48:15 +01:00
Lukas W
7019cabb51 Merge branch 'stable-1.2' into fix/qt5-vst 2017-11-25 12:36:34 +01:00
Lukas W
46ef3c6a11 Fix rpmalloc debug build with GCC < 5 2017-11-25 12:09:10 +01:00
Lukas W
23cb3852ac VstEmbed: Remove obsolete CMake flags 2017-11-24 15:39:53 +01:00
Lukas W
e95e3793b4 Merge pull request #3991 from PhysSong/fix/qt5-vst
Some fixes/enhancements for #3786
2017-11-24 14:40:24 +01:00
Lukas W
3d47344297 Travis: Enable Linux/Qt4 builds 2017-11-24 12:59:40 +01:00
Lukas W
a8aa3e153f VST: Fix Qt4 compilation 2017-11-24 12:46:06 +01:00
Oskar Wallgren
c6ae1dcba6 Automation Editor - delete automation point (#3986)
Fix regression from b68dc572a3
Let the right mouse button delete the automation point like before
and add the space above it too.
2017-11-24 05:38:47 +01:00
Oskar Wallgren
55076d0bb0 Unsolo mixer channels on delete (#3982)
If a mixer channel is soloed when it's deleted the other channels are left in the
state their in which is, for the most part, muted. Solve this by clearing mixer
channels on delete.
2017-11-21 20:56:54 +01:00
Hyunin Song
72e882af88 Add a fallback logic for VST embedding methods 2017-11-20 15:57:29 +09:00
Hyunin Song
55ce90ec00 Try to improve embedding method logic 2017-11-20 15:46:57 +09:00
Hyunin Song
463d02e299 Move SC_CLOSE handling code 2017-11-19 14:25:39 +09:00
Hyunin Song
7da7a70d60 Add Win32 embedding 2017-11-19 14:25:39 +09:00
Hyunin Song
b0f64dea7f Restrict "qt" embed method to Qt5 only 2017-11-19 14:25:39 +09:00
Hyunin Song
df3c07bbed Fix Qt4 compatibility 2017-11-19 14:25:33 +09:00
Hyunjin Song
514ae34df3 Fix automation pattern regressions (#3977)
Change the default value of ignoreSurroundingPoints in AutomationPattern::putValue to true, which was false in #3352.
Fixes automation filpping bug and some potential issues.
2017-11-19 10:50:22 +09:00
Oskar Wallgren
3de3ea6b16 Revert accidental submodule changes 2017-11-18 16:30:00 +01:00
Oskar Wallgren
b68dc572a3 Automtion Editor - left click response
When you left click an existing value the automation point will only
snap to the new value if it is higher. If it is lower the mouse click
event will 'break'.

Cleanup. Remove statement that will always evaluate as 'true'.
2017-11-18 15:04:20 +01:00
Oskar Wallgren
01265ace66 Default project when cancelling project loading (#3941)
Default project when cancelling project loading

If a user isn't aware that the loading of a project has been
cancelled, it may be in an incomplete state. Saving such a project
will overwrite the original file and result in data loss. This is
solved by loading the default project on cancelling project loading.

Add Mixer::clearNewPlayHandles() to prevent crash when cancelling
loading of a single streamed instrument.
2017-11-17 02:03:49 +01:00
Hyunjin Song
601046aa03 Fix CAPS plugin build with some compilers (#3972) 2017-11-15 10:18:03 -05:00
Tres Finocchiaro
de98781df4 Use "soundfonts" folder, not "sf2" 2017-11-14 21:55:25 -05:00
Dominic Clark
7ed9bea9fb Disable plugin transparency on Qt5 (#3934) 2017-11-13 08:52:08 +09:00
Lukas W
358a251cff VstEmbed: Support changing embed method without restart 2017-11-10 09:18:40 +01:00
Lukas W
f9f4d0cb9c VstEmbed: Store embed method on plugin start
Avoids bugs when embed method is changed in setup dialog while VSTs are
running.
2017-11-10 08:12:20 +01:00
Lukas W
a8311a7b49 Vst: Fix widget deletion 2017-11-10 08:02:29 +01:00
Hussam Eddin Alhomsi
0dbbdd9f4c Update the grid after changing the quantization value in automation editor 2017-11-09 16:31:20 +01:00
Hussam Eddin Alhomsi
43ae3c6376 Update patterns in song editor after shifting their notes by semitones in piano roll. (#3961)
After shifting notes up/down, call rearrangeAllNotes() to sort notes and dataChanged()
to update the pattern the Song Editor.
2017-11-09 16:29:45 +01:00
Tres Finocchiaro
d4d909cd9e Add libjack.so.0 fallback logic for AppImages (#3958)
Add libjack.so.0 fallback logic
2017-11-09 01:57:20 -05:00
Hyunjin Song
48b9b6508e Fix visual glitch with automation patterns (#3945)
Fix off-by-one visual glitch in automation editor and automation pattern view
2017-11-09 06:58:51 +09:00
Hussam Eddin Alhomsi
8baf42fca0 Remove text from project notes of factory templates. (#3939) 2017-11-07 14:21:12 -05:00
Lukas W
0dbdafc1f8 CMake: Fix non-existing target warnings 2017-11-07 12:06:52 +01:00
follower
eb09ff6f25 Fix off-by-one/heap-buffer-overflow as reported by ASAN.
It's probably not the best "solution" but it should hopefully be
one less category of crash-on-close on Mac.

ASAN a.k.a Clang "AddressSanitizer".
2017-11-07 11:56:49 +01:00
Lukas W
6fd38fee9f Fix qt5-x11embed submodule reference 2017-11-07 11:21:00 +01:00
Lukas W
2b6f366063 CMake: Only link qx11embedcontainer on Linux 2017-11-07 11:03:37 +01:00
Lukas W
6eb447deb7 Merge branch 'stable-1.2' into fix/qt5-vst
# Conflicts:
#	.gitmodules
#	.travis/linux..install.sh
#	CMakeLists.txt
#	plugins/vst_base/CMakeLists.txt
#	src/3rdparty/CMakeLists.txt
2017-11-07 10:58:52 +01:00
Lukas W
e3ba9ba9be Update qt5-x11embed submodule for CMake changes 2017-11-06 19:15:57 +01:00
Lukas W
421a85d2e1 Update qt5-x11embed submodule 2017-11-06 18:32:56 +01:00
Lukas W
e95fdcc37d Add missing includes 2017-11-06 18:29:09 +01:00
Lukas W
472a74d252 Minor fixes 2017-11-06 16:31:12 +01:00
Lukas W
134dae80d5 VstEmbed: Add missing find_package instruction for Qt5X11Extras 2017-11-06 11:39:39 +01:00
Lukas W
415316f722 VstEmbed: Remove obsolete CMake flags 2017-11-06 11:39:19 +01:00
Lukas W
6839746344 VstEmbed: Allow selecting method at runtime 2017-11-06 11:17:10 +01:00
Dan Williams
298f1ec335 Fix recent files (#3872)
* Fix templates and recent files on KDE.

Workaround for https://bugs.kde.org/show_bug.cgi?id=337491 , Call into KDE stuff to stop it adding accelerators.

* Fix & in recent files.

Escape & as && when building the recent file lists, and reverse that when getting the file name.
2017-11-04 17:31:41 +09:00
Hyunjin Song
a3c7328f9c Fix wrong value interpolation (#3929) 2017-11-04 08:54:33 +09:00
Oskar Wallgren
0c31cf49c0 linearToLogScale() - Input validation (#3932) 2017-11-03 09:41:28 +01:00
tresf
f15acb8620 Specify architecture for AppImage 2017-11-01 01:01:09 -04:00
Oskar Wallgren
88b940fa05 LADSPA - Fix various floating point errors (#3927)
* swh - Dyson Compressor, fix NaN

* swh - shaper_1187, division with 0

* Division with 0 in calf limiter
2017-10-31 02:33:37 +01:00
Michael Gregorius
7e107f5914 Fix #3842: Opening a project with LB302 produces a noise burst
Fix the noise burst described in #3842 by removing the second
initialization of vca_a to 9 in the constructor of lb302Synth.
2017-10-30 15:48:10 +01:00
Hyunjin Song
60e9b2f474 Fix crashes and deadlocks with previewing preset (#3905)
* Fix crash when closing while previewing preset

* Fix deadlock on previewing presets while playing arpeggio
2017-10-29 20:26:28 +09:00
Oskar Wallgren
9715da332b Deleting Automation Points at coarser quantization
Regression from f9ab2dec02
Don't follow quantization as you will have to move the
cursor that length before any deletion is made.
2017-10-26 02:38:15 +02:00
Hussam Eddin Alhomsi
05971cac6a Fix monstro's osc 3 vol knob values. (#3912) 2017-10-24 21:01:26 +02:00
Oskar Wallgren
f9ab2dec02 Automation Point delete radius and size (#3902)
* Fix Automation Point delete radius. At lower zoom deleting would miss
automation points to delete and at higher zoom it would be too generous
and remove neighbouring points.

* Increase smallest Automation Point radius. For  visibility. The smallest
Automatin Point radius was tiny.
2017-10-24 17:42:30 +02:00
Hyunjin Song
de20d76c8e Ignore release frames for single-streamed instruments (#3900)
Let InstrumentSoundShaping::releaseFrames() ignore release frames for single-streamed instruments. And make it return 0 if m_instrumentTrack->instrument() is NULL.
2017-10-24 00:21:25 +09:00
Lukas W
fbfcb43aeb Merge pull request #3881 from zonkmachine/arppatternsort
Note sorting algorithm rework
2017-10-19 08:49:31 +02:00
Oskar Wallgren
9341acd129 Remove obsolete function - qSort() 2017-10-19 03:35:55 +02:00
Lukas W
8d6cb120b9 Replace MemoryManager implementation with rpmalloc (#3873)
* Replace MemoryManager implementation with rpmalloc
    Fixes #3865
* Travis: Specify OSX image for Qt5 build
2017-10-18 17:02:40 +02:00
Oskar Wallgren
81966fa1a6 Sort note patterns after both position and key 2017-10-18 14:41:00 +02:00
Lukas W
20ea945cee Fix typo 2017-10-18 10:24:36 +02:00
Lukas W
4594e7e237 Merge pull request #3889 from Umcaruje/portaudiowindowsbyebye
Disable portaudio on Windows
2017-10-18 09:49:18 +02:00
Lukas W
9d560a3104 ZynAddSubFx: Fix preset loading (#3891)
Fix regression from #1719
Fixes #3886
2017-10-17 15:46:16 -04:00
Lukas W
6fc4577f10 PlayHandle: Zero out buffer before processing
Fixes buffer noises when instruments don't write the whole buffer, such as
bitinvader. Related:
* #3884 (comment): https://github.com/LMMS/lmms/pull/3884#issuecomment-337170598
* #3883
# #3383
2017-10-17 20:24:34 +02:00
Umcaruje
6e5d82f954 Disable portaudio on Windows 2017-10-16 22:08:12 +02:00
Tres Finocchiaro
3e90e37352 Add AppImage support to Linux builds (#3688)
Add AppImage support
2017-10-16 15:09:30 -04:00
Tres Finocchiaro
c051e9bf34 Use weak loading of libjack (#3887) 2017-10-16 14:46:25 -04:00
Tres Finocchiaro
221d0cb355 Switch Travis-CI to Qt5.8 (#3885) 2017-10-16 13:48:38 -04:00
Hyunjin Song
eaa7b0dd7c Fix sfxr buffer noise (#3883) 2017-10-16 17:14:47 +02:00
Lukas W
2930ef69cd Merge pull request #3884 from PhysSong/nphdestruct
Fix missing destructor call in NotePlayHandle
2017-10-16 09:23:31 +02:00
Hyunin Song
2d07efd1dd Replace NotePlayHandle::done() to the actual destructor 2017-10-16 15:26:05 +09:00
David CARLIER
54f3eccad7 linkage issue fixes due to inlined functions (#3815) 2017-10-10 21:35:02 -04:00
Rebecca LaVie
f24f8c7b00 LCD Updates (#3864) 2017-10-10 19:05:37 +02:00
Oskar Wallgren
d0cd42ee5e Update project year 2017-10-10 18:43:03 +02:00
Oskar Wallgren
2d583db990 Fix arpeggio sort mode (#3867)
When in sort mode and playing over multiple base notes, in the
beginning of the notes there is a chance that the notes will play
together as an ordinary chord instead of arpeggiate.
This is a regression from 6650dd3.

Fixes #3342
2017-10-10 06:05:11 +02:00
Oskar Wallgren
6da87379b4 Arpeggiator fixes (#3858)
Set 'master note' for silent notes on sort mode.
Prevent silent notes to play as ordinary notes in the background
when they are waiting for their turn to arpeggiate.

Remove unnecessary test (it will always return TRUE).

Slower default speed (200ms).
2017-10-09 06:29:23 +02:00
David CARLIER
e7e24935b3 catching-up for openbsd sndio support + applying abs call fix (#3839) 2017-10-03 00:47:45 +02:00
Lukas W
ffa1b63f05 Fix VST effects embedding 2017-09-22 12:06:19 +02:00
Lukas W
df37833ca5 Merge branch 'stable-1.2' into fix/qt5-vst
# Conflicts:
#	plugins/vst_base/RemoteVstPlugin.cpp
2017-09-22 11:50:19 +02:00
Lukas W
e7d06759b5 Fix Qt4 VST embed option 2017-09-01 14:26:46 +02:00
Lukas W
ddab534656 Allow switching VST embed method at compile time 2017-09-01 14:18:55 +02:00
Lukas W
f7dab939ae Merge branch 'qt5-vst-2-stable' into fix/qt5-vst
# Conflicts:
#	plugins/vst_base/RemoteVstPlugin.cpp
#	plugins/vst_base/VstPlugin.cpp
2017-09-01 14:18:26 +02:00
Lukas W
bd33475534 Fix x11embed for non qt5+linux 2017-09-01 12:20:20 +02:00
Lukas W
0d3aaf667b .gitmodules: Use https URL 2017-09-01 12:20:20 +02:00
Lukas W
def2b7d509 Move X11EmbedContainer to submodule 2017-09-01 12:20:20 +02:00
Lukas W
d9626e9e3b Move X11EmbedContainer.h to include 2017-09-01 12:20:20 +02:00
Lukas W
000fe2da7b Travis: Fix xcb package name 2017-09-01 12:20:20 +02:00
Lukas W
dc4a3875a3 X11EmbedContainer: Don't grab mouse in acceptClient, more debugging msgs 2017-09-01 12:20:20 +02:00
Lukas W
7ce60c247a Travis: Add missing packages 2017-09-01 12:20:20 +02:00
Lukas W
8fdcc6ccac Fix compile on Windows 2017-09-01 12:20:20 +02:00
Lukas W
0e311ffd47 X11Embed: Remove flag causing embedding to fail 2017-09-01 12:20:20 +02:00
Lukas W
f097be6c40 RemoteVst: Fix flickering when moving window 2017-09-01 12:20:20 +02:00
Lukas W
adef05fb71 X11EmbedContainer: Fix XEMBED protocol implementation 2017-09-01 12:20:20 +02:00
Lukas W
e661d26f42 Add X11EmbedContainer Qt5 port 2017-09-01 12:20:20 +02:00
Tres Finocchiaro
47d0e66fcc Re-enable SF2
Per https://github.com/LMMS/lmms/pull/3489#issuecomment-292976079
2017-09-01 12:18:46 +02:00
Javier Serrano Polo
7a9396d6ea Let Wine handle the window interface 2017-09-01 12:18:46 +02:00
Javier Serrano Polo
d04fd9f542 FluidSynth is currently undistributable 2017-09-01 12:18:46 +02:00
Javier Serrano Polo
2d35de4182 Debug window ID 2017-09-01 12:18:46 +02:00
Javier Serrano Polo
f87f3638e1 Use window instead of embedder application 2017-09-01 12:18:46 +02:00
Javier Serrano Polo
12f6ea5566 C++11 is enabled by default now 2017-09-01 12:18:46 +02:00
Javier Serrano Polo
e3d3052e42 Enable C++11 on Windows 2017-09-01 12:18:46 +02:00
Javier Serrano Polo
6395cd4c41 Enable C++11 2017-09-01 12:18:46 +02:00
Javier Serrano Polo
ebe63d1425 Fixes for Windows builds 2017-09-01 12:08:48 +02:00
Javier Serrano Polo
878dd94e8d Embed in a separate window 2017-09-01 12:08:48 +02:00
Javier Serrano Polo
a81f4ca8e9 Embed VST GUI in subwindow 2017-09-01 12:08:48 +02:00
109 changed files with 3772 additions and 1031 deletions

6
.gitmodules vendored Normal file
View File

@@ -0,0 +1,6 @@
[submodule "src/3rdparty/qt5-x11embed"]
path = src/3rdparty/qt5-x11embed
url = https://github.com/Lukas-W/qt5-x11embed.git
[submodule "src/3rdparty/rpmalloc/rpmalloc"]
path = src/3rdparty/rpmalloc/rpmalloc
url = https://github.com/rampantpixels/rpmalloc.git

View File

@@ -12,10 +12,12 @@ matrix:
- env: TARGET_OS=win64
- os: osx
osx_image: xcode8.2
- env: QT5=
- env: QT5=True
- env: QT5=True TARGET_OS=win32
- env: QT5=True TARGET_OS=win64
- os: osx
osx_image: xcode8.2
env: QT5=True
before_install:
- . ${TRAVIS_BUILD_DIR}/.travis/${TRAVIS_OS_NAME}.${TARGET_OS}.before_install.sh

View File

@@ -1,5 +1,6 @@
#!/usr/bin/env bash
sudo add-apt-repository ppa:beineri/opt-qt592-trusty -y
sudo add-apt-repository ppa:andrewrk/libgroove -y
sudo sed -e "s/trusty/precise/" -i \
/etc/apt/sources.list.d/andrewrk-libgroove-trusty.list

View File

@@ -1,17 +1,25 @@
#!/usr/bin/env bash
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
libasound2-dev libjack-dev libsdl-dev libsamplerate0-dev libstk0-dev stk
libfluidsynth-dev portaudio19-dev g++-multilib libfltk1.3-dev
libgig-dev libsoundio-dev"
VST_PACKAGES="wine-dev libqt5x11extras5-dev qtbase5-private-dev libxcb-util0-dev libxcb-keysyms1-dev"
# Help with unmet dependencies
PACKAGES="$PACKAGES libjack0"
PACKAGES="$PACKAGES $VST_PACKAGES libjack0"
if [ $QT5 ]; then
PACKAGES="$PACKAGES qtbase5-dev qttools5-dev-tools qttools5-dev"
PACKAGES="$PACKAGES qt59base qt59translations qt59tools"
else
PACKAGES="$PACKAGES libqt4-dev"
fi
sudo apt-get install -y $PACKAGES
# kxstudio repo offers Carla; avoid package conflicts (wine, etc) by running last
sudo add-apt-repository -y ppa:kxstudio-debian/libs
sudo add-apt-repository -y ppa:kxstudio-debian/apps
sudo apt-get update
sudo apt-get install -y carla-git

View File

@@ -1,3 +1,7 @@
#!/usr/bin/env bash
if [ $QT5 ]; then
unset QTDIR QT_PLUGIN_PATH LD_LIBRARY_PATH
source /opt/qt59/bin/qt59-env.sh
fi
cmake -DUSE_WERROR=ON $CMAKE_FLAGS ..

View File

@@ -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 CMP0045 NEW)
CMAKE_POLICY(SET CMP0050 OLD)
ENDIF()
ENDIF(COMMAND CMAKE_POLICY)
@@ -20,7 +21,7 @@ INCLUDE(FindPkgConfig)
STRING(TOUPPER "${CMAKE_PROJECT_NAME}" PROJECT_NAME_UCASE)
# Updated by maintenance tasks
SET(PROJECT_YEAR 2015)
SET(PROJECT_YEAR 2017)
SET(PROJECT_AUTHOR "LMMS Developers")
SET(PROJECT_URL "https://lmms.io")
@@ -30,7 +31,7 @@ SET(PROJECT_COPYRIGHT "2008-${PROJECT_YEAR} ${PROJECT_AUTHOR}")
SET(VERSION_MAJOR "1")
SET(VERSION_MINOR "2")
SET(VERSION_RELEASE "0")
SET(VERSION_STAGE "rc4")
SET(VERSION_STAGE "rc5")
SET(VERSION_BUILD "0")
SET(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_RELEASE}")
IF(VERSION_STAGE)
@@ -51,6 +52,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_WEAKJACK "Loosely link JACK libraries" ON)
OPTION(WANT_MP3LAME "Include MP3/Lame support" ON)
OPTION(WANT_OGGVORBIS "Include OGG/Vorbis support" ON)
OPTION(WANT_PULSEAUDIO "Include PulseAudio support" ON)
@@ -84,12 +86,14 @@ IF(LMMS_BUILD_WIN32)
SET(WANT_ALSA OFF)
SET(WANT_JACK OFF)
SET(WANT_PULSEAUDIO OFF)
SET(WANT_PORTAUDIO OFF)
SET(WANT_SOUNDIO OFF)
SET(WANT_WINMM ON)
SET(LMMS_HAVE_WINMM TRUE)
SET(STATUS_ALSA "<not supported on this platform>")
SET(STATUS_JACK "<not supported on this platform>")
SET(STATUS_PULSEAUDIO "<not supported on this platform>")
SET(STATUS_PORTAUDIO "<disabled on this platform>")
SET(STATUS_SOUNDIO "<disabled in this release>")
SET(STATUS_WINMM "OK")
SET(STATUS_APPLEMIDI "<not supported on this platform>")
@@ -152,6 +156,14 @@ IF(WANT_QT5)
Qt5::Xml
)
IF(LMMS_BUILD_LINUX)
FIND_PACKAGE(Qt5X11Extras REQUIRED)
LIST(APPEND QT_LIBRARIES Qt5::X11Extras)
ENDIF()
# Resolve Qt5::qmake to full path for use in packaging scripts
GET_TARGET_PROPERTY(QT_QMAKE_EXECUTABLE "${Qt5Core_QMAKE_EXECUTABLE}" IMPORTED_LOCATION)
FIND_PACKAGE(Qt5Test)
SET(QT_QTTEST_LIBRARY Qt5::Test)
ELSE()
@@ -364,8 +376,16 @@ ENDIF(NOT LMMS_HAVE_ALSA)
IF(WANT_JACK)
PKG_CHECK_MODULES(JACK jack>=0.77)
IF(JACK_FOUND)
IF(WANT_WEAKJACK)
SET(LMMS_HAVE_WEAKJACK TRUE)
SET(STATUS_JACK "OK (weak linking enabled)")
SET(JACK_INCLUDE_DIRS "")
# use dlsym instead
SET(JACK_LIBRARIES "dl")
ELSE()
SET(STATUS_JACK "OK")
ENDIF()
SET(LMMS_HAVE_JACK TRUE)
SET(STATUS_JACK "OK")
ELSE(JACK_FOUND)
SET(STATUS_JACK "not found, please install libjack0.100.0-dev (or similar) "
"if you require JACK support")
@@ -424,7 +444,11 @@ IF(WANT_VST)
FIND_PACKAGE(Wine)
IF(WINE_FOUND)
SET(LMMS_SUPPORT_VST TRUE)
SET(STATUS_VST "OK")
IF(WINE_LIBRARY_FIX)
SET(STATUS_VST "OK, with workaround linking ${WINE_LIBRARY_FIX}")
ELSE()
SET(STATUS_VST "OK")
ENDIF()
ELSEIF(WANT_VST_NOWINE)
SET(LMMS_SUPPORT_VST TRUE)
SET(STATUS_VST "OK")

View File

@@ -1,4 +1,19 @@
INSTALL(FILES lmms.png DESTINATION "${DATA_DIR}/pixmaps")
INSTALL(FILES lmms DESTINATION "${DATA_DIR}/menu")
INSTALL(FILES lmms.svg DESTINATION "${DATA_DIR}/icons/hicolor/scalable/apps")
INSTALL(FILES project.svg DESTINATION "${DATA_DIR}/icons/hicolor/scalable/mimetypes/" RENAME "application-x-lmms-project.svg")
INSTALL(FILES lmms.desktop DESTINATION "${DATA_DIR}/applications")
INSTALL(FILES lmms.xml DESTINATION "${DATA_DIR}/mime/packages")
# AppImage creation target
SET(APPIMAGE_FILE "${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}-${VERSION}-linux-${CMAKE_SYSTEM_PROCESSOR}.AppImage")
CONFIGURE_FILE("package_linux.sh.in" "${CMAKE_BINARY_DIR}/package_linux.sh" @ONLY)
FILE(REMOVE "${APPIMAGE_FILE}")
ADD_CUSTOM_TARGET(removeappimage
COMMAND rm -f "${APPIMAGE_FILE}"
COMMENT "Removing old AppImage")
ADD_CUSTOM_TARGET(appimage
COMMAND chmod +x "${CMAKE_BINARY_DIR}/package_linux.sh"
COMMAND "${CMAKE_BINARY_DIR}/package_linux.sh"
COMMENT "Generating AppImage")
ADD_DEPENDENCIES(appimage removeappimage)

View File

@@ -1,4 +1,4 @@
?package(lmms):needs="X11" section="Apps/Sound" \
title="LMMS" hints="Audio" command="/usr/bin/lmms" \
longtitle="LMMS" \
icon="/usr/share/pixmaps/lmms.png"
icon="/usr/share/icons/hicolor/scalable/apps/lmms.svg"

View File

@@ -1,10 +1,10 @@
[Desktop Entry]
Name=LMMS
GenericName=music production suite
GenericName=Music production suite
GenericName[ca]=Programari de producció musical
GenericName[de]=Software zur Musik-Produktion
GenericName[fr]=Ensemble pour la production musicale
Comment=easy music production for everyone!
Comment=Music sequencer and synthesizer
Comment[ca]=Producció fàcil de música per a tothom!
Comment[fr]=Production facile de musique pour tout le monde !
Icon=lmms

1540
cmake/linux/lmms.svg Normal file

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 54 KiB

View File

@@ -4,11 +4,7 @@
<sub-class-of type="application/xml"/>
<comment>LMMS project</comment>
<comment xml:lang="ca">Projecte LMMS</comment>
<glob pattern="*.mmp"/>
<glob pattern="*.mmpz"/>
<magic priority="80">
<match type="string" value="&lt;!DOCTYPE multimedia-project" offset="0:256"/>
<match type="string" value="&lt;multimedia-project" offset="0:64"/>
</magic>
<glob pattern="*.mmp"/>
</mime-type>
</mime-info>

View File

@@ -0,0 +1,198 @@
#!/usr/bin/env bash
# Creates Linux ".AppImage" for @PROJECT_NAME_UCASE@
#
# Depends: linuxdeployqt
#
# Notes: Will attempt to fetch linuxdeployqt automatically (x86_64 only)
# See Also: https://github.com/probonopd/linuxdeployqt/blob/master/BUILDING.md
set -e
USERBIN="$HOME/bin"
LINUXDEPLOYQT="$USERBIN/linuxdeployqt"
APPIMAGETOOL="$USERBIN/appimagetool"
VERBOSITY=2 # 3=debug
LOGFILE="@CMAKE_BINARY_DIR@/appimage.log"
APPDIR="@CMAKE_BINARY_DIR@/@PROJECT_NAME_UCASE@.AppDir/"
DESKTOPFILE="${APPDIR}usr/share/applications/lmms.desktop"
STRIP=""
# Don't strip for Debug|RelWithDebInfo builds
if [[ "@CMAKE_BUILD_TYPE@" == *"Deb"* ]]; then
STRIP="-no-strip"
fi
# Console colors
RED="\\x1B[1;31m"
GREEN="\\x1B[1;32m"
YELLOW="\\x1B[1;33m"
PLAIN="\\x1B[0m"
function error {
echo -e " ${PLAIN}[${RED}error${PLAIN}] ${1}"
return 1
}
function success {
echo -e " ${PLAIN}[${GREEN}success${PLAIN}] ${1}"
}
function skipped {
echo -e " ${PLAIN}[${YELLOW}skipped${PLAIN}] ${1}"
}
# Blindly assume system arch is appimage arch
ARCH=$(arch)
export ARCH
# Check for problematic install locations
INSTALL=$(echo "@CMAKE_INSTALL_PREFIX@" | sed 's/\/*$//g')
if [ "$INSTALL" == "/usr/local" ] || [ "$INSTALL" == "/usr" ] ; then
error "Incompatible CMAKE_INSTALL_PREFIX for creating AppImage: @CMAKE_INSTALL_PREFIX@"
fi
echo -e "\nWriting verbose output to \"${LOGFILE}\""
# Ensure linuxdeployqt uses the same qmake version as cmake
export PATH="$HOME/bin:$(dirname "@QT_QMAKE_EXECUTABLE@")":$PATH
# Fetch portable linuxdeployqt if cache is older than $DAYSOLD
echo -e "\nDownloading linuxdeployqt to ${LINUXDEPLOYQT}..."
mkdir -p "$HOME/bin"
DAYSOLD=2
if env -i which linuxdeployqt > /dev/null 2>&1; then
skipped "System already provides this utility"
elif ! find "$LINUXDEPLOYQT" -mtime -$DAYSOLD 2>/dev/null|grep -q "." > /dev/null 2>&1; then
url="https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-$(uname -p).AppImage"
echo " [.......] Couldn't find linuxdeployqt newer than $DAYSOLD days old"
echo " [.......] Downloading ($(uname -p)): ${url}"
wget "$url" -O "$LINUXDEPLOYQT" -q || (rm "$LINUXDEPLOYQT" && false)
chmod +x "$LINUXDEPLOYQT"
touch "$LINUXDEPLOYQT"
success "Downloaded $LINUXDEPLOYQT"
"$LINUXDEPLOYQT" --appimage-extract > /dev/null 2>&1
mv "squashfs-root/usr/bin/appimagetool" "$APPIMAGETOOL"
success "Extracted $APPIMAGETOOL"
mv "squashfs-root/usr/bin/mksquashfs" "$USERBIN/mksquashfs"
success "Extracted $USERBIN/mksquashfs"
rm -rf "squashfs-root/"
else
skipped "$LINUXDEPLOYQT is less than $DAYSOLD days old"
fi
# Make skeleton AppDir
echo -e "\nCreating ${APPDIR}..."
rm -rf "${APPDIR}"
mkdir -p "${APPDIR}usr"
success "Created ${APPDIR}"
# Clone install to AppDir
echo -e "\nCopying @CMAKE_INSTALL_PREFIX@ to ${APPDIR}..."
cp -R "@CMAKE_INSTALL_PREFIX@/." "${APPDIR}usr"
rm -rf "${APPDIR}usr/include"
success "${APPDIR}"
# Copy rawwaves directory for stk/mallets
mkdir -p "${APPDIR}usr/share/stk/"
cp -R /usr/share/stk/rawwaves/ "${APPDIR}usr/share/stk/"
# Create a wrapper script which calls the lmms executable
mv "${APPDIR}usr/bin/lmms" "${APPDIR}usr/bin/lmms.real"
# shellcheck disable=SC1083
cat >"${APPDIR}usr/bin/lmms" <<EOL
#!/usr/bin/env bash
DIR="\$( cd "\$( dirname "\${BASH_SOURCE[0]}" )" && pwd )"
if which carla > /dev/null 2>&1; then
CARLAPATH="$(which carla)"
CARLAPREFIX="\${CARLAPATH%/bin*}"
echo "Carla appears to be installed on this system at \$CARLAPREFIX/lib[64]/carla so we'll use it."
export LD_LIBRARY_PATH=\$CARLAPREFIX/lib/carla:\$CARLAPREFIX/lib64/carla:\$LD_LIBRARY_PATH
else
echo "Carla does not appear to be installed. That's OK, please ignore any related library errors."
fi
export LD_LIBRARY_PATH=\$DIR/usr/lib/:\$DIR/usr/lib/lmms:\$LD_LIBRARY_PATH
# Prevent segfault on VirualBox
if lsmod |grep vboxguest > /dev/null 2>&1; then
echo "VirtualBox detected. Forcing libgl software rendering."
export LIBGL_ALWAYS_SOFTWARE=1;
fi
if ldconfig -p | grep libjack.so.0 > /dev/null 2>&1; then
echo "Jack appears to be installed on this system, so we'll use it."
else
echo "Jack does not appear to be installed. That's OK, we'll use a dummy version instead."
export LD_LIBRARY_PATH=\$DIR/usr/lib/lmms/optional:\$LD_LIBRARY_PATH
fi
QT_X11_NO_NATIVE_MENUBAR=1 \$DIR/usr/bin/lmms.real "\$@"
EOL
chmod +x "${APPDIR}usr/bin/lmms"
# Per https://github.com/probonopd/linuxdeployqt/issues/129
unset LD_LIBRARY_PATH
# Ensure linuxdeployqt can find shared objects
export LD_LIBRARY_PATH="${APPDIR}usr/lib/lmms/":$LD_LIBRARY_PATH
# Handle wine linking
if [ -d "@WINE_LIBRARY_FIX@" ]; then
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:@WINE_LIBRARY_FIX@:@WINE_LIBRARY_FIX@wine/
fi
# Move executables so linuxdeployqt can find them
ZYNLIB="${APPDIR}usr/lib/lmms/RemoteZynAddSubFx"
VSTLIB="${APPDIR}usr/lib/lmms/RemoteVstPlugin.exe.so"
ZYNBIN="${APPDIR}usr/bin/RemoteZynAddSubFx"
VSTBIN="${APPDIR}usr/bin/RemoteVstPlugin.exe.so"
mv "$ZYNLIB" "$ZYNBIN"
mv "$VSTLIB" "$VSTBIN"
# Patch the desktop file
sed -i 's/.*Exec=.*/Exec=lmms.real/' "$DESKTOPFILE"
# Fix linking for soft-linked plugins
for file in "${APPDIR}usr/lib/lmms/"*.so; do
thisfile="${APPDIR}usr/lib/lmms/${file##*/}"
executables="${executables} -executable=$thisfile"
done
executables="${executables} -executable=${ZYNBIN}"
executables="${executables} -executable=${VSTBIN}"
executables="${executables} -executable=${APPDIR}usr/lib/lmms/ladspa/imp_1199.so"
executables="${executables} -executable=${APPDIR}usr/lib/lmms/ladspa/imbeq_1197.so"
executables="${executables} -executable=${APPDIR}usr/lib/lmms/ladspa/pitch_scale_1193.so"
executables="${executables} -executable=${APPDIR}usr/lib/lmms/ladspa/pitch_scale_1194.so"
# Bundle both qt and non-qt dependencies into appimage format
echo -e "\nBundling and relinking system dependencies..."
echo -e ">>>>> linuxdeployqt" > "$LOGFILE"
# shellcheck disable=SC2086
"$LINUXDEPLOYQT" "$DESKTOPFILE" $executables -bundle-non-qt-libs -verbose=$VERBOSITY $STRIP >> "$LOGFILE" 2>&1
success "Bundled and relinked dependencies"
# Link to original location so lmms can find them
ln -sr "$ZYNBIN" "$ZYNLIB"
ln -sr "$VSTBIN" "$VSTLIB"
# Remove wine library conflict
rm -f "${APPDIR}/usr/lib/libwine.so.1"
# Use system-provided carla
rm -f "${APPDIR}usr/lib/"libcarla*.so
# Remove problematic jack library, replace with weakjack
if [ -e "${APPDIR}/usr/lib/libjack.so.0" ]; then
rm -f "${APPDIR}/usr/lib/libjack.so.0"
mkdir -p "${APPDIR}usr/lib/lmms/optional/"
cp "@CMAKE_BINARY_DIR@/optional/weakjack.so" "${APPDIR}usr/lib/lmms/optional/weakjack.so"
ln -sr "${APPDIR}usr/lib/lmms/optional/weakjack.so" "${APPDIR}usr/lib/lmms/optional/libjack.so.0"
fi
# Create AppImage
echo -e "\nFinishing the AppImage..."
echo -e "\n\n>>>>> appimagetool" >> "$LOGFILE"
"$APPIMAGETOOL" "${APPDIR}" "@APPIMAGE_FILE@" >> "$LOGFILE" 2>&1
success "Created @APPIMAGE_FILE@"
echo -e "\nFinished"

View File

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 66 KiB

View File

@@ -7,6 +7,8 @@
# WINE_DEFINITIONS - Compiler switches required for using wine
#
LIST(APPEND CMAKE_PREFIX_PATH /opt/wine-stable /opt/wine-devel /opt/wine-staging)
FIND_PATH(WINE_INCLUDE_DIR windows/windows.h PATH_SUFFIXES wine)
FIND_LIBRARY(WINE_LIBRARY NAMES wine PATH_SUFFIXES wine i386-linux-gnu/wine)
FIND_PROGRAM(WINE_CXX NAMES wineg++ winegcc winegcc64 winegcc32)
@@ -14,6 +16,26 @@ FIND_PROGRAM(WINE_CXX NAMES wineg++ winegcc winegcc64 winegcc32)
set(WINE_INCLUDE_DIRS ${WINE_INCLUDE_DIR} )
set(WINE_LIBRARIES ${WINE_LIBRARY} )
# Handle wine linking problems
EXEC_PROGRAM(${WINE_CXX} ARGS "-v -m32 /dev/zero" OUTPUT_VARIABLE WINEBUILD_OUTPUT)
# Debian systems
IF("${WINEBUILD_OUTPUT}" MATCHES ".*x86_64-linux-gnu/wine/libwinecrt0.a.*")
SET(WINE_LIBRARY_FIX "/usr/lib/i386-linux-gnu/" )
# Fedora systems
ELSEIF("${WINEBUILD_OUTPUT}" MATCHES "/usr/lib/lib64/wine/libwinecrt0.a.*")
SET(WINE_LIBRARY_FIX "/usr/lib/i386/")
# Wine stable
ELSEIF("${WINEBUILD_OUTPUT}" MATCHES "/opt/wine-stable/lib64/wine/libwinecrt0.a.*")
SET(WINE_LIBRARY_FIX "/opt/wine-stable/lib/")
# Wine development
ELSEIF("${WINEBUILD_OUTPUT}" MATCHES "/opt/wine-devel/lib64/wine/libwinecrt0.a.*")
SET(WINE_LIBRARY_FIX "/opt/wine-devel/lib/")
# Wine staging
ELSEIF("${WINEBUILD_OUTPUT}" MATCHES "/opt/wine-staging/lib64/wine/libwinecrt0.a.*")
SET(WINE_LIBRARY_FIX "/opt/wine-staging/lib/")
ENDIF()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Wine DEFAULT_MSG WINE_LIBRARIES WINE_INCLUDE_DIRS)

View File

@@ -30,11 +30,7 @@
<ControllerRackView visible="1" width="258" height="142" x="836" y="407" maximized="0" minimized="0"/>
<pianoroll visible="0" width="640" height="480" x="1" y="1" maximized="0" minimized="0"/>
<automationeditor visible="0" width="640" height="400" x="56" y="255" maximized="0" minimized="0"/>
<projectnotes visible="0" width="640" height="400" x="1" y="1" maximized="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:'Verdana'; font-size:11pt; font-weight:600; 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=" font-family:'Droid Sans'; font-size:10pt; font-weight:400; color:#e0e0e0;">Put down your project notes here.</span></p></body></html>]]></projectnotes>
<projectnotes visible="0" width="640" height="400" x="1" y="1" maximized="0" minimized="0"></projectnotes>
<timeline lp0pos="0" lp1pos="192" lpstate="0"/>
<controllers/>
</song>

View File

@@ -78,11 +78,7 @@
<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>
<projectnotes width="640" x="700" y="10" maximized="0" height="400" visible="0" minimized="0"></projectnotes>
<timeline lp1pos="192" lp0pos="0" lpstate="0"/>
<controllers/>
</song>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 643 B

After

Width:  |  Height:  |  Size: 808 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 637 B

After

Width:  |  Height:  |  Size: 799 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 641 B

After

Width:  |  Height:  |  Size: 803 B

View File

@@ -28,11 +28,16 @@
#include "lmmsconfig.h"
#ifdef LMMS_HAVE_JACK
#ifndef LMMS_HAVE_WEAKJACK
#include <jack/jack.h>
#else
#include "AudioWeakJack.h"
#endif
#include <QtCore/QVector>
#include <QtCore/QList>
#include <QtCore/QMap>
#include <QMutexLocker>
#include "AudioDevice.h"
#include "AudioDeviceSetupWidget.h"
@@ -103,6 +108,7 @@ private:
bool m_active;
bool m_stopped;
QMutex m_processingMutex;
MidiJack *m_midiClient;
QVector<jack_port_t *> m_outputPorts;

View File

@@ -72,6 +72,8 @@ private:
struct sio_hdl *m_hdl;
struct sio_par m_par;
bool m_convertEndian;
} ;

162
include/AudioWeakJack.def Normal file
View File

@@ -0,0 +1,162 @@
/* macro-absraction of the JACK API
*
* see weak_libjack.c for details, in general arguments are:
*
* [required], [return type], [name], [arguments], [code or return value]
*
* This file is included multiple times with different macro definitions
* do not add header guards.
* see https://en.wikibooks.org/wiki/C_Programming/Preprocessor#X-Macros
*/
#ifdef USE_WEAK_JACK
/* <jack/jack.h> */
JCFUN(1, int, client_close, 0)
JCFUN(1, char*, get_client_name, NULL)
JVFUN(0, on_shutdown, (jack_client_t *c, JackShutdownCallback s, void *a), (c,s,a),)
JVFUN(0, on_info_shutdown, (jack_client_t *c, JackInfoShutdownCallback s, void *a), (c,s,a),)
JPFUN(1, int, set_process_callback, (jack_client_t *c, JackProcessCallback p, void *a), (c,p,a), -1)
JPFUN(1, int, set_freewheel_callback, (jack_client_t *c, JackFreewheelCallback p, void *a), (c,p,a), -1)
JPFUN(1, int, set_buffer_size_callback, (jack_client_t *c, JackBufferSizeCallback p, void *a), (c,p,a), -1)
JPFUN(1, int, set_sample_rate_callback, (jack_client_t *c, JackSampleRateCallback p, void *a), (c,p,a), -1)
JPFUN(1, int, set_port_registration_callback, (jack_client_t *c, JackPortRegistrationCallback p, void *a), (c,p,a), -1)
JPFUN(1, int, set_port_connect_callback, (jack_client_t *c, JackPortConnectCallback p, void *a), (c,p,a), -1)
JPFUN(1, int, set_graph_order_callback, (jack_client_t *c, JackGraphOrderCallback g, void *a), (c,g,a), -1)
JPFUN(1, int, set_xrun_callback, (jack_client_t *c, JackXRunCallback g, void *a), (c,g,a), -1)
JPFUN(1, int, set_latency_callback, (jack_client_t *c, JackLatencyCallback g, void *a), (c,g,a), -1)
JVFUN(1, set_error_function, (void (*f)(const char *)), (f),)
JVFUN(1, set_info_function, (void (*f)(const char *)), (f),)
JCFUN(1, int, activate, -1)
JCFUN(1, int, deactivate, -1)
JPFUN(1, int, client_name_size, (), (), 32)
JCFUN(1, jack_nframes_t, get_sample_rate, 0)
JCFUN(1, jack_nframes_t, get_buffer_size, 0)
JPFUN(1, jack_nframes_t, frames_since_cycle_start, (const jack_client_t *c), (c), 0)
JPFUN(1, jack_nframes_t, frame_time, (const jack_client_t *c), (c), 0)
JPFUN(1, jack_nframes_t, last_frame_time, (const jack_client_t *c), (c), 0)
JPFUN(1, jack_time_t, get_time, (void), (), 0)
JCFUN(1, float, cpu_load, 0)
JCFUN(1, int, is_realtime, 0)
JPFUN(1, int, set_freewheel, (jack_client_t *c, int o), (c,o), 0)
JPFUN(1, int, set_buffer_size, (jack_client_t *c, jack_nframes_t b), (c,b), 0)
JCFUN(0, int, recompute_total_latencies, 0)
JPFUN(0, jack_nframes_t, port_get_total_latency, (jack_client_t *c, jack_port_t *p), (c,p), 0)
JVFUN(0, port_get_latency_range, (jack_port_t *p, jack_latency_callback_mode_t m, jack_latency_range_t *r), (p,m,r), if (r) {r->min = r->max = 0;})
JVFUN(0, port_set_latency_range, (jack_port_t *p, jack_latency_callback_mode_t m, jack_latency_range_t *r), (p,m,r),)
JPFUN(1, void*, port_get_buffer, (jack_port_t *p, jack_nframes_t n), (p,n), NULL)
JPFUN(1, int, port_request_monitor, (jack_port_t *p, int o), (p,o), 0)
JPFUN(1, int, port_ensure_monitor, (jack_port_t *p, int o), (p,o), 0)
JPFUN(1, int, port_monitoring_input, (jack_port_t *p), (p), 0)
JPFUN(1, const char*, port_name, (const jack_port_t *p), (p), NULL)
JPFUN(1, const char*, port_short_name, (const jack_port_t *p), (p), NULL)
JPFUN(1, int, port_flags, (const jack_port_t *p), (p), 0)
JPFUN(1, const char**, get_ports,(jack_client_t *c, const char *p, const char *t, unsigned long f), (c,p,t,f), NULL)
JPFUN(1, int, port_name_size, (void), (), 0)
JPFUN(1, int, port_type_size, (void), (), 0)
JPFUN(1, size_t, port_type_get_buffer_size, (jack_client_t *c, const char *t), (c,t), 0)
JPFUN(1, jack_port_t*, port_by_name, (jack_client_t *c, const char *n), (c,n), NULL)
JPFUN(1, jack_port_t*, port_by_id, (jack_client_t *c, jack_port_id_t i), (c,i), NULL)
JPFUN(1, jack_port_t*, port_register, (jack_client_t *c, const char *n, const char *t, unsigned long f, unsigned long b), (c,n,t,f,b), NULL)
JPFUN(1, int, port_unregister, (jack_client_t *c, jack_port_t *p), (c,p), 0)
JPFUN(1, const char *, port_type, (const jack_port_t *p), (p), 0)
JPFUN(1, const char **, port_get_connections, (const jack_port_t *p), (p), 0)
JPFUN(1, const char **, port_get_all_connections, (const jack_client_t *c, const jack_port_t *p), (c,p), 0)
JPFUN(1, int, port_set_name, (jack_port_t *p, const char *n), (p,n), -1)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
JXFUN(0, int, port_rename, (jack_client_t *c, jack_port_t *p, const char *n), (c,p,n), return jack_port_set_name (p,n);)
#pragma GCC diagnostic pop
JPFUN(1, int, port_get_aliases, (const jack_port_t *port, char* const aliases[2]), (port,aliases), 0)
JPFUN(1, int, port_disconnect, (jack_client_t *c, jack_port_t *p), (c,p), 0)
JPFUN(1, int, connect, (jack_client_t *c, const char *s, const char *d), (c,s,d), -1)
JPFUN(1, int, disconnect, (jack_client_t *c, const char *s, const char *d), (c,s,d), -1)
JVFUN(0, free, (void *p), (p), free(p);)
JCFUN(1, jack_nframes_t, cycle_wait, 0)
JVFUN(1, cycle_signal, (jack_client_t *c, int s), (c,s),)
JPFUN(1, int, set_process_thread, (jack_client_t *c, JackThreadCallback p, void *a), (c,p,a), -1)
JPFUN(1, int, set_thread_init_callback, (jack_client_t *c, JackThreadInitCallback p, void *a), (c,p,a), -1)
JPFUN(1, int, transport_locate, (jack_client_t *c, jack_nframes_t f), (c,f), 0)
JVFUN(1, transport_start, (jack_client_t *c), (c),)
JVFUN(1, transport_stop, (jack_client_t *c), (c),)
JPFUN(1, jack_nframes_t, get_current_transport_frame, (const jack_client_t *c), (c), 0)
JXFUN(1, jack_transport_state_t, transport_query, (const jack_client_t *c, jack_position_t *p), (c,p), memset(p, 0, sizeof(jack_position_t)); return JackTransportStopped;)
JPFUN(1, int, set_sync_callback, (jack_client_t *c, JackSyncCallback p, void *a), (c,p,a), -1)
JPFUN(1, int, set_timebase_callback, (jack_client_t *c, int l, JackTimebaseCallback p, void *a), (c,l,p,a), -1)
JCFUN(1, int, release_timebase, 0)
/* <jack/midiport.h> */
JPFUN(1, uint32_t, midi_get_event_count, (void* p), (p), 0)
JPFUN(1, int, midi_event_get, (jack_midi_event_t *e, void *p, uint32_t i), (e,p,i), -1)
JPFUN(1, int, midi_event_write, (void *b, jack_nframes_t t, const jack_midi_data_t *d, size_t s), (b,t,d,s), -1)
JVFUN(1, midi_clear_buffer, (void *b), (b),)
/* <jack/session.h> */
JPFUN(0, int, set_session_callback, (jack_client_t *c, JackSessionCallback s, void *a), (c,s,a), -1)
JPFUN(0, int, session_reply, (jack_client_t *c, jack_session_event_t *e), (c,e), -1)
JVFUN(0, session_event_free, (jack_session_event_t *e), (e), )
/* <jack/ringbuffer.h> */
JPFUN(1, jack_ringbuffer_t *, ringbuffer_create, (size_t s), (s), NULL)
JVFUN(1, ringbuffer_free, (jack_ringbuffer_t *rb), (rb), )
JVFUN(1, ringbuffer_reset, (jack_ringbuffer_t *rb), (rb), )
JVFUN(1, ringbuffer_read_advance, (jack_ringbuffer_t *rb, size_t c), (rb,c), )
JVFUN(1, ringbuffer_write_advance, (jack_ringbuffer_t *rb, size_t c), (rb,c), )
JPFUN(1, size_t, ringbuffer_read_space, (const jack_ringbuffer_t *rb), (rb), 0)
JPFUN(1, size_t, ringbuffer_write_space, (const jack_ringbuffer_t *rb), (rb), 0)
JPFUN(1, size_t, ringbuffer_read, (jack_ringbuffer_t *rb, char *d, size_t c), (rb,d,c), 0)
JPFUN(1, size_t, ringbuffer_write, (jack_ringbuffer_t *rb, const char *s, size_t c), (rb,s,c), 0)
JPFUN(0, int, ringbuffer_mlock, (jack_ringbuffer_t *rb), (rb), 0)
JVFUN(0, ringbuffer_get_read_vector, (const jack_ringbuffer_t *rb, jack_ringbuffer_data_t *v), (rb,v), if (v) {v->buf=NULL; v->len=0;} )
JVFUN(0, ringbuffer_get_write_vector, (const jack_ringbuffer_t *rb, jack_ringbuffer_data_t *v), (rb,v), if (v) {v->buf=NULL; v->len=0;} )
JPFUN(0, size_t, ringbuffer_peek, (jack_ringbuffer_t *rb, char *d, size_t c), (rb,d,c), 0)
/* <jack/thread.h> */
JCFUN(0, int, client_real_time_priority, 0)
JCFUN(0, int, client_max_real_time_priority, 0)
JPFUN(0, int, acquire_real_time_scheduling, (jack_native_thread_t t, int p), (t,p), 0)
JPFUN(0, int, drop_real_time_scheduling, (jack_native_thread_t t), (t), 0)
JPFUN(0, int, client_stop_thread, (jack_client_t* c, jack_native_thread_t t), (c,t), 0)
JPFUN(0, int, client_kill_thread, (jack_client_t* c, jack_native_thread_t t), (c,t), 0)
#ifndef _WIN32
JVFUN(0, set_thread_creator, (jack_thread_creator_t c), (c),)
#endif
JPFUN(1, int, client_create_thread, \
(jack_client_t* c, jack_native_thread_t *t, int p, int r, void *(*f)(void*), void *a), (c,t,p,r,f,a), 0)
#ifndef NO_JACK_METADATA
/* <jack/uuid.h> - TODO*/
/* <jack/jack.h> */
JPFUN(0, char *, get_uuid_for_client_name, (jack_client_t* c, const char* n), (c,n), NULL)
JPFUN(0, char *, get_client_name_by_uuid, (jack_client_t* c, const char* u), (c,u), NULL)
JPFUN(0, jack_uuid_t, port_uuid, (const jack_port_t *p), (p), 0)
/* <jack/metadata.h> */
JPFUN(0, int, set_property, (jack_client_t* c, jack_uuid_t s, const char* k, const char* v, const char* t), (c,s,k,v,t), -1)
JXFUN(0, int, get_property, (jack_uuid_t s, const char* k, char** v, char** t), (s,k,v,t), if (v) *v=NULL; if (t) *t=NULL; return -1;)
JVFUN(0, free_description, (jack_description_t* d, int f), (d,f),)
JXFUN(0, int, get_properties, (jack_uuid_t s, jack_description_t* d), (s,d), if (d) {d->properties = NULL; d->property_cnt = 0;} return -1;)
JXFUN(0, int, get_all_properties, (jack_description_t** d), (d), if (d) *d=NULL; return -1;)
JPFUN(0, int, remove_property, (jack_client_t* c, jack_uuid_t s, const char* k), (c,s,k), -1)
JPFUN(0, int, remove_properties, (jack_client_t* c, jack_uuid_t s), (c,s), -1)
JPFUN(0, int, remove_all_properties, (jack_client_t* c), (c), -1)
JPFUN(0, int, set_property_change_callback, (jack_client_t *c, JackPropertyChangeCallback s, void *a), (c,s,a), -1)
#endif
/* <jack/statistics.h> */
JCFUN(1, float, get_max_delayed_usecs, 0.0)
JCFUN(1, float, get_xrun_delayed_usecs, 0.0)
JVFUN(0, reset_max_delayed_usecs, (jack_client_t *c), (c),)
#endif // end USE_WEAK_JACK

237
include/AudioWeakJack.h Normal file
View File

@@ -0,0 +1,237 @@
/* runtime/weak dynamic JACK linking
*
* (C) 2014 Robin Gareus <robin@gareus.org>
*
* The wrapped jack API itself is
* (C) 2001 Paul Davis
* (C) 2004 Jack O'Quin
*
* 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, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _WEAK_JACK_H
#define _WEAK_JACK_H
// LMMS uses LMMS_HAVE_WEAKJACK instead
#ifndef USE_WEAK_JACK
#define USE_WEAK_JACK
#endif
// LMMS doesn't use metadata.h
#ifndef NO_JACK_METADATA
#define NO_JACK_METADATA
#endif
#ifdef __cplusplus
extern "C"
{
#endif
/** check if libjack is available
*
* return 0 if libjack is dynamically linked of was
* successfully dl-opened. Otherwise:
*
* -1: library was not initialized
* -2: libjack was not found
* > 0 bitwise flags:
* 1: a required function was not found in libjack
* 2: jack_client_open was not found in libjack
*/
int have_libjack(void);
#ifdef __cplusplus
}
#endif
#ifdef USE_WEAK_JACK
/* <jack/jack.h> */
#define jack_client_close WJACK_client_close
#define jack_get_client_name WJACK_get_client_name
#define jack_get_sample_rate WJACK_get_sample_rate
#define jack_get_buffer_size WJACK_get_buffer_size
#define jack_frames_since_cycle_start WJACK_frames_since_cycle_start
#define jack_frame_time WJACK_frame_time
#define jack_last_frame_time WJACK_last_frame_time
#define jack_get_time WJACK_get_time
#define jack_cpu_load WJACK_cpu_load
#define jack_is_realtime WJACK_is_realtime
#define jack_client_name_size WJACK_client_name_size
#define jack_set_freewheel WJACK_set_freewheel
#define jack_set_buffer_size WJACK_set_buffer_size
#define jack_on_shutdown WJACK_on_shutdown
#define jack_on_info_shutdown WJACK_on_info_shutdown
#define jack_set_process_callback WJACK_set_process_callback
#define jack_set_freewheel_callback WJACK_set_freewheel_callback
#define jack_set_buffer_size_callback WJACK_set_buffer_size_callback
#define jack_set_sample_rate_callback WJACK_set_sample_rate_callback
#define jack_set_port_registration_callback WJACK_set_port_registration_callback
#define jack_set_port_connect_callback WJACK_set_port_connect_callback
#define jack_set_graph_order_callback WJACK_set_graph_order_callback
#define jack_set_xrun_callback WJACK_set_xrun_callback
#define jack_set_latency_callback WJACK_set_latency_callback
#define jack_set_error_function WJACK_set_error_function
#define jack_set_info_function WJACK_set_info_function
#define jack_activate WJACK_activate
#define jack_deactivate WJACK_deactivate
#define jack_recompute_total_latencies WJACK_recompute_total_latencies
#define jack_port_get_total_latency WJACK_port_get_total_latency
#define jack_port_get_latency_range WJACK_port_get_latency_range
#define jack_port_set_latency_range WJACK_port_set_latency_range
#define jack_port_get_buffer WJACK_port_get_buffer
#define jack_port_request_monitor WJACK_port_request_monitor
#define jack_port_ensure_monitor WJACK_port_ensure_monitor
#define jack_port_monitoring_input WJACK_port_monitoring_input
#define jack_port_name WJACK_port_name
#define jack_port_short_name WJACK_port_short_name
#define jack_port_flags WJACK_port_flags
#define jack_get_ports WJACK_get_ports
#define jack_port_name_size WJACK_port_name_size
#define jack_port_type_size WJACK_port_type_size
#define jack_port_type_get_buffer_size WJACK_port_type_get_buffer_size
#define jack_port_by_name WJACK_port_by_name
#define jack_port_by_id WJACK_port_by_id
#define jack_port_set_name WJACK_port_set_name
#define jack_port_get_aliases WJACK_port_get_aliases
#define jack_port_rename WJACK_port_rename
#define jack_port_disconnect WJACK_port_disconnect
#define jack_port_register WJACK_port_register
#define jack_port_unregister WJACK_port_unregister
#define jack_port_type WJACK_port_type
#define jack_port_get_connections WJACK_port_get_connections
#define jack_port_get_all_connections WJACK_port_get_all_connections
#define jack_connect WJACK_connect
#define jack_disconnect WJACK_disconnect
#define jack_free WJACK_free
#define jack_cycle_wait WJACK_cycle_wait
#define jack_cycle_signal WJACK_cycle_signal
#define jack_set_process_thread WJACK_set_process_thread
#define jack_set_thread_init_callback WJACK_set_thread_init_callback
/* <jack/transport.h> */
#define jack_get_current_transport_frame WJACK_get_current_transport_frame
#define jack_transport_locate WJACK_transport_locate
#define jack_transport_start WJACK_transport_start
#define jack_transport_stop WJACK_transport_stop
#define jack_transport_query WJACK_transport_query
#define jack_set_sync_callback WJACK_set_sync_callback
#define jack_set_timebase_callback WJACK_set_timebase_callback
#define jack_release_timebase WJACK_release_timebase
/* <jack/midiport.h> */
#define jack_midi_get_event_count WJACK_midi_get_event_count
#define jack_midi_event_get WJACK_midi_event_get
#define jack_midi_event_write WJACK_midi_event_write
#define jack_midi_clear_buffer WJACK_midi_clear_buffer
/* <jack/session.h> */
#define jack_set_session_callback WJACK_set_session_callback
#define jack_session_reply WJACK_session_reply
#define jack_session_event_free WJACK_session_event_free
/* <jack/ringbuffer.h> */
#define jack_ringbuffer_create WJACK_ringbuffer_create
#define jack_ringbuffer_free WJACK_ringbuffer_free
#define jack_ringbuffer_reset WJACK_ringbuffer_reset
#define jack_ringbuffer_read_advance WJACK_ringbuffer_read_advance
#define jack_ringbuffer_write_advance WJACK_ringbuffer_write_advance
#define jack_ringbuffer_read_space WJACK_ringbuffer_read_space
#define jack_ringbuffer_write_space WJACK_ringbuffer_write_space
#define jack_ringbuffer_read WJACK_ringbuffer_read
#define jack_ringbuffer_write WJACK_ringbuffer_write
#define jack_ringbuffer_mlock WJACK_ringbuffer_mlock
#define jack_ringbuffer_get_read_vector WJACK_ringbuffer_get_read_vector
#define jack_ringbuffer_get_write_vector WJACK_ringbuffer_get_write_vector
#define jack_ringbuffer_peek WJACK_ringbuffer_peek
/* <jack/thread.h> */
#define jack_client_real_time_priority WJACK_client_real_time_priority
#define jack_client_max_real_time_priority WJACK_client_max_real_time_priority
#define jack_acquire_real_time_scheduling WJACK_acquire_real_time_scheduling
#define jack_client_create_thread WJACK_client_create_thread
#define jack_drop_real_time_scheduling WJACK_drop_real_time_scheduling
#define jack_client_stop_thread WJACK_client_stop_thread
#define jack_client_kill_thread WJACK_client_kill_thread
#define jack_set_thread_creator WJACK_set_thread_creator
#define jack_client_open WJACK_client_client_openXXX
#ifndef NO_JACK_METADATA
/* <jack/metadata.h> */
#define jack_get_uuid_for_client_name WJACK_get_uuid_for_client_name
#define jack_get_client_name_by_uuid WJACK_get_client_name_by_uuid
#define jack_port_uuid WJACK_port_uuid
#define jack_set_property WJACK_set_property
#define jack_get_property WJACK_get_property
#define jack_free_description WJACK_free_description
#define jack_get_properties WJACK_get_properties
#define jack_get_all_properties WJACK_get_all_properties
#define jack_remove_property WJACK_remove_property
#define jack_remove_properties WJACK_remove_properties
#define jack_remove_all_properties WJACK_remove_all_properties
#define jack_set_property_change_callback WJACK_set_property_change_callback
#endif
/* <jack/statistics.h> */
#define jack_get_max_delayed_usecs WJACK_get_max_delayed_usecs
#define jack_get_xrun_delayed_usecs WJACK_get_xrun_delayed_usecs
#define jack_reset_max_delayed_usecs WJACK_reset_max_delayed_usecs
#endif // end USE_WEAK_JACK
#include <jack/jack.h>
#include <jack/transport.h>
#include <jack/ringbuffer.h>
#include <jack/midiport.h>
#include <jack/session.h>
#include <jack/thread.h>
#ifndef NO_JACK_METADATA
#include <jack/metadata.h>
#endif
#ifdef USE_WEAK_JACK
#undef jack_client_open
/* var-args hack */
#ifdef __cplusplus
extern "C" {
#endif
void (* WJACK_get_client_open (void)) (void);
jack_client_t * WJACK_no_client_open (const char *client_name, jack_options_t options, jack_status_t *status, ...);
#ifdef __cplusplus
}
#endif
#define jack_client_open(...) \
( \
(WJACK_get_client_open() != NULL) \
? ((jack_client_t* (*)(const char *, jack_options_t, jack_status_t *, ...))(WJACK_get_client_open()))(__VA_ARGS__) \
: WJACK_no_client_open(__VA_ARGS__) \
)
#endif // end USE_WEAK_JACK
#endif // _WEAK_JACK_H

View File

@@ -25,6 +25,7 @@
#ifndef AUTOMATABLE_MODEL_H
#define AUTOMATABLE_MODEL_H
#include <QtCore/QMap>
#include <QtCore/QMutex>
#include "JournallingObject.h"

View File

@@ -132,6 +132,7 @@ protected:
void getSelectedValues(timeMap & selected_values );
void drawLine( int x0, float y0, int x1, float y1 );
void removePoints( int x0, int x1 );
protected slots:
void play();

View File

@@ -80,7 +80,7 @@ public:
MidiTime putValue( const MidiTime & time,
const float value,
const bool quantPos = true,
const bool ignoreSurroundingPoints = false );
const bool ignoreSurroundingPoints = true );
void removeValue( const MidiTime & time );

View File

@@ -41,9 +41,9 @@ public:
virtual bool play( MidiTime _start, const fpp_t _frames,
const f_cnt_t _frame_base, int _tco_num = -1 );
virtual void updateAfterTrackAdd();
virtual void updateAfterTrackAdd() override;
inline virtual QString nodeName() const
inline virtual QString nodeName() const override
{
return "bbtrackcontainer";
}

View File

@@ -32,9 +32,9 @@
#include <QtCore/QPair>
#include <QtCore/QStringList>
#include <QtCore/QVector>
#include <QtCore/QObject>
#include "export.h"
#include "MemoryManager.h"
class LmmsCore;
@@ -44,16 +44,16 @@ const QString TEMPLATE_PATH = "templates/";
const QString PRESETS_PATH = "presets/";
const QString SAMPLES_PATH = "samples/";
const QString GIG_PATH = "samples/gig/";
const QString SF2_PATH = "samples/sf2/";
const QString SF2_PATH = "samples/soundfonts/";
const QString LADSPA_PATH ="plugins/ladspa/";
const QString DEFAULT_THEME_PATH = "themes/default/";
const QString TRACK_ICON_PATH = "track_icons/";
const QString LOCALE_PATH = "locale/";
class EXPORT ConfigManager
class EXPORT ConfigManager : public QObject
{
MM_OPERATORS
Q_OBJECT
public:
static inline ConfigManager * inst()
{
@@ -210,6 +210,9 @@ public:
return m_recentlyOpenedProjects;
}
static QStringList availabeVstEmbedMethods();
QString vstEmbedMethod() const;
// returns true if the working dir (e.g. ~/lmms) exists on disk
bool hasWorkingDir() const;
@@ -242,6 +245,8 @@ public:
// creates the working directory & subdirectories on disk.
void createWorkingDir();
signals:
void valueChanged( QString cls, QString attribute, QString value );
private:
static ConfigManager * s_instanceOfMe;

View File

@@ -31,15 +31,26 @@
#ifdef LMMS_BUILD_WIN32
#include <windows.h>
#if QT_VERSION >= 0x050000
#include <QAbstractNativeEventFilter>
#endif
#endif
#if defined(LMMS_BUILD_WIN32) && QT_VERSION >= 0x050000
class MainApplication : public QApplication, public QAbstractNativeEventFilter
#else
class MainApplication : public QApplication
#endif
{
public:
MainApplication(int& argc, char** argv);
bool event(QEvent* event);
#ifdef LMMS_BUILD_WIN32
bool winEventFilter(MSG* msg, long* result);
#if QT_VERSION >= 0x050000
bool nativeEventFilter(const QByteArray& eventType, void* message,
long* result);
#endif
#endif
inline QString& queuedFile()
{

View File

@@ -1,6 +1,7 @@
/*
* MemoryManager.h - A lightweight, generic memory manager for LMMS
* MemoryManager.h
*
* Copyright (c) 2017 Lukas W <lukaswhl/at/gmail.com>
* Copyright (c) 2014 Vesa Kivimäki
* Copyright (c) 2007-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
@@ -26,81 +27,22 @@
#ifndef MEMORY_MANAGER_H
#define MEMORY_MANAGER_H
#include <QtCore/QVector>
#include <QtCore/QMutex>
#include <QtCore/QHash>
#include "MemoryHelper.h"
#include <cstddef>
#include <vector>
#include "export.h"
class QReadWriteLock;
const int MM_CHUNK_SIZE = 64; // granularity of managed memory
const int MM_INITIAL_CHUNKS = 1024 * 1024; // how many chunks to allocate at startup - TODO: make configurable
const int MM_INCREMENT_CHUNKS = 16 * 1024; // min. amount of chunks to increment at a time
struct MemoryPool
{
void * m_pool;
char * m_free;
size_t m_chunks;
QMutex m_mutex;
MemoryPool() :
m_pool( NULL ),
m_free( NULL ),
m_chunks( 0 )
{}
MemoryPool( size_t chunks ) :
m_chunks( chunks )
{
m_free = reinterpret_cast<char*>( MemoryHelper::alignedMalloc( chunks ) );
memset( m_free, 1, chunks );
}
MemoryPool( const MemoryPool & mp ) :
m_pool( mp.m_pool ),
m_free( mp.m_free ),
m_chunks( mp.m_chunks ),
m_mutex()
{}
MemoryPool & operator = ( const MemoryPool & mp )
{
m_pool = mp.m_pool;
m_free = mp.m_free;
m_chunks = mp.m_chunks;
return *this;
}
void * getChunks( int chunksNeeded );
void releaseChunks( void * ptr, int chunks );
};
struct PtrInfo
{
int chunks;
MemoryPool * memPool;
};
typedef QVector<MemoryPool> MemoryPoolVector;
typedef QHash<void*, PtrInfo> PointerInfoMap;
class EXPORT MemoryManager
{
public:
static bool init();
struct ThreadGuard
{
ThreadGuard();
~ThreadGuard();
};
static void * alloc( size_t size );
static void free( void * ptr );
static int extend( int chunks ); // returns index of created pool (for use by alloc)
static void cleanup();
private:
static MemoryPoolVector s_memoryPools;
static QReadWriteLock s_poolMutex;
static PointerInfoMap s_pointerInfo;
static QMutex s_pointerMutex;
};
template<typename T>
@@ -147,32 +89,4 @@ static void operator delete[] ( void * ptr ) \
// and just for symmetry...
#define MM_FREE( ptr ) MemoryManager::free( ptr )
// for debugging purposes
#define MM_OPERATORS_DEBUG \
public: \
static void * operator new ( size_t size ) \
{ \
qDebug( "MM_OPERATORS_DEBUG: new called for %d bytes", size ); \
return MemoryManager::alloc( size ); \
} \
static void * operator new[] ( size_t size ) \
{ \
qDebug( "MM_OPERATORS_DEBUG: new[] called for %d bytes", size ); \
return MemoryManager::alloc( size ); \
} \
static void operator delete ( void * ptr ) \
{ \
qDebug( "MM_OPERATORS_DEBUG: delete called for %p", ptr ); \
MemoryManager::free( ptr ); \
} \
static void operator delete[] ( void * ptr ) \
{ \
qDebug( "MM_OPERATORS_DEBUG: delete[] called for %p", ptr ); \
MemoryManager::free( ptr ); \
}
#endif

View File

@@ -28,8 +28,12 @@
#include "lmmsconfig.h"
#ifdef LMMS_HAVE_JACK
#ifndef LMMS_HAVE_WEAKJACK
#include <jack/jack.h>
#include <jack/midiport.h>
#else
#include "AudioWeakJack.h"
#endif
#include <QtCore/QThread>
#include <QMutex>

View File

@@ -155,6 +155,7 @@ public:
void initDevices();
void clear();
void clearNewPlayHandles();
// audio-device-stuff

View File

@@ -113,11 +113,19 @@ public:
void quantizeLength( const int qGrid );
void quantizePos( const int qGrid );
static inline bool lessThan( Note * &lhs, Note * &rhs )
static inline bool lessThan( const Note * lhs, const Note * rhs )
{
// function to compare two notes - must be called explictly when
// using qSort
return (bool) ((int) ( *lhs ).pos() < (int) ( *rhs ).pos());
if( (int)( *lhs ).pos() < (int)( *rhs ).pos() )
{
return true;
}
else if( (int)( *lhs ).pos() > (int)( *rhs ).pos() )
{
return false;
}
return ( (int)( *lhs ).key() > (int)( *rhs ).key() );
}
inline bool selected() const

View File

@@ -66,8 +66,7 @@ public:
NotePlayHandle* parent = NULL,
int midiEventChannel = -1,
Origin origin = OriginPattern );
virtual ~NotePlayHandle() {}
void done();
virtual ~NotePlayHandle();
void * operator new ( size_t size, void * p )
{

View File

@@ -28,6 +28,7 @@
#include <memory>
#include <QtCore/QFileInfo>
#include <QtCore/QHash>
#include <QtCore/QList>
#include "export.h"

View File

@@ -414,6 +414,7 @@ private:
enum RemoteMessageIDs
{
IdUndefined,
IdHostInfoGotten,
IdInitDone,
IdQuit,
IdSampleRateInformation,
@@ -427,6 +428,8 @@ enum RemoteMessageIDs
IdChangeInputOutputCount,
IdShowUI,
IdHideUI,
IdToggleUI,
IdIsUIVisible,
IdSaveSettingsToString,
IdSaveSettingsToFile,
IdLoadSettingsFromString,
@@ -781,7 +784,13 @@ public:
#endif
}
bool init( const QString &pluginExecutable, bool waitForInitDoneMsg );
bool init( const QString &pluginExecutable, bool waitForInitDoneMsg, QStringList extraArgs = {} );
inline void waitForHostInfoGotten()
{
m_failed = waitForMessage( IdHostInfoGotten ).id
!= IdHostInfoGotten;
}
inline void waitForInitDone( bool _busyWaiting = true )
{
@@ -801,18 +810,21 @@ public:
unlock();
}
void showUI()
virtual void toggleUI()
{
lock();
sendMessage( IdShowUI );
sendMessage( IdToggleUI );
unlock();
}
void hideUI()
int isUIVisible()
{
lock();
sendMessage( IdHideUI );
sendMessage( IdIsUIVisible );
unlock();
message m = waitForMessage( IdIsUIVisible );
return m.id != IdIsUIVisible ? -1 : m.getInt() ? 1 : 0;
}
inline bool failed() const
@@ -830,6 +842,9 @@ public:
m_commMutex.unlock();
}
public slots:
virtual void showUI();
virtual void hideUI();
protected:
inline void setSplittedChannels( bool _on )
@@ -1206,6 +1221,7 @@ RemotePluginClient::RemotePluginClient( const char * socketPath ) :
m_vstSyncData = (VstSyncData *) m_shmQtID.data();
m_bufferSize = m_vstSyncData->m_bufferSize;
m_sampleRate = m_vstSyncData->m_sampleRate;
sendMessage( IdHostInfoGotten );
return;
}
#else
@@ -1233,6 +1249,7 @@ RemotePluginClient::RemotePluginClient( const char * socketPath ) :
{
m_bufferSize = m_vstSyncData->m_bufferSize;
m_sampleRate = m_vstSyncData->m_sampleRate;
sendMessage( IdHostInfoGotten );
// detach segment
if( shmdt(m_vstSyncData) == -1 )
@@ -1248,6 +1265,12 @@ RemotePluginClient::RemotePluginClient( const char * socketPath ) :
// if attaching shared memory fails
sendMessage( IdSampleRateInformation );
sendMessage( IdBufferSizeInformation );
if( waitForMessage( IdBufferSizeInformation ).id
!= IdBufferSizeInformation )
{
fprintf( stderr, "Could not get buffer size information\n" );
}
sendMessage( IdHostInfoGotten );
}

View File

@@ -204,7 +204,8 @@ private:
MswMap m_midiIfaceSetupWidgets;
trMap m_midiIfaceNames;
QComboBox* m_vstEmbedComboBox;
QString m_vstEmbedMethod;
} ;

View File

@@ -33,6 +33,7 @@
#include "TrackContainer.h"
#include "Controller.h"
#include "MeterModel.h"
#include "Mixer.h"
#include "VstSyncController.h"
@@ -229,6 +230,17 @@ public:
return m_loadingProject;
}
void loadingCancelled()
{
m_isCancelled = true;
Engine::mixer()->clearNewPlayHandles();
}
bool isCancelled()
{
return m_isCancelled;
}
bool isModified() const
{
return m_modified;
@@ -358,6 +370,7 @@ private:
volatile bool m_paused;
bool m_loadingProject;
bool m_isCancelled;
QStringList m_errors;

View File

@@ -34,7 +34,9 @@
#ifdef LMMS_DEBUG
#include <assert.h>
#else
#define assert(x) ((void)(x))
#ifndef assert
#define assert(x) ((void)(x))
#endif
#endif
#include <cstdio>

View File

@@ -229,11 +229,12 @@ static inline float logToLinearScale( float min, float max, float value )
static inline float linearToLogScale( float min, float max, float value )
{
static const float EXP = 1.0f / F_E;
const float val = ( value - min ) / ( max - min );
const float valueLimited = qBound( min, value, max);
const float val = ( valueLimited - min ) / ( max - min );
if( min < 0 )
{
const float mmax = qMax( qAbs( min ), qAbs( max ) );
float result = signedPowf( value / mmax, EXP ) * mmax;
float result = signedPowf( valueLimited / mmax, EXP ) * mmax;
return isnan( result ) ? 0 : result;
}
float result = powf( val, EXP ) * ( max - min ) + min;

View File

@@ -32,8 +32,7 @@ EqHandle::EqHandle( int num, int x, int y ):
m_width( x ),
m_heigth( y ),
m_mousePressed( false ),
m_active( false ),
m_handleMoved( false )
m_active( false )
{
setFlag( ItemIsMovable );
setFlag( ItemSendsGeometryChanges );
@@ -41,7 +40,6 @@ EqHandle::EqHandle( int num, int x, int y ):
float totalHeight = 36;
m_pixelsPerUnitHeight = ( m_heigth ) / ( totalHeight );
setMouseHover( false );
connect( this, SIGNAL( positionChanged() ), this, SLOT( handleMoved() ) );
}
@@ -93,14 +91,6 @@ float EqHandle::yPixelToGain(float y , int h, float pixelPerUnitHeight )
void EqHandle::handleMoved()
{
m_handleMoved = true;
}
void EqHandle::paint( QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget )
{
painter->setRenderHint( QPainter::Antialiasing, true );
@@ -189,6 +179,11 @@ void EqHandle::loadPixmap()
m_circlePixmap = PLUGIN_NAME::getIconPixmap( fileName.toLatin1() );
}
bool EqHandle::mousePressed() const
{
return m_mousePressed;
}
@@ -463,22 +458,6 @@ void EqHandle::setHandleActive( bool a )
void EqHandle::setHandleMoved( bool a )
{
m_handleMoved = a;
}
bool EqHandle::getHandleMoved()
{
return m_handleMoved;
}
void EqHandle::sethp12()
{
m_hp12 = true;

View File

@@ -71,8 +71,7 @@ public:
void setMouseHover( bool d );
bool isActiveHandle();
void setHandleActive( bool a );
void setHandleMoved(bool a);
bool getHandleMoved();
bool mousePressed() const;
void sethp12();
void sethp24();
void sethp48();
@@ -95,7 +94,6 @@ protected:
private:
double calculateGain( const double freq, const double a1, const double a2, const double b0, const double b1, const double b2 );
void loadPixmap();
float m_pixelsPerUnitWidth;
float m_pixelsPerUnitHeight;
float m_scale;
@@ -111,11 +109,7 @@ private:
float m_resonance;
bool m_mousePressed;
bool m_active;
bool m_handleMoved;
QPixmap m_circlePixmap;
private slots:
void handleMoved();
};

View File

@@ -104,7 +104,7 @@ void EqParameterWidget::updateHandle()
m_eqcurve->setModelChanged( true );
for( int i = 0 ; i < bandCount(); i++ )
{
if ( m_handleList->at( i )->getHandleMoved() == false ) //prevents a short circuit between handle and data model
if ( !m_handleList->at( i )->mousePressed() ) //prevents a short circuit between handle and data model
{
//sets the band on active if a fader or a knob is moved
bool hover = false; // prevents an action if handle is moved
@@ -126,7 +126,6 @@ void EqParameterWidget::updateHandle()
else
{
m_handleList->at( i )->setHandleActive( m_bands[i].active->value() );
m_handleList->at( i )->setHandleMoved( false );
}
}
if ( m_bands[0].hp12->value() ) m_handleList->at( 0 )->sethp12();

View File

@@ -2,6 +2,10 @@ INCLUDE(BuildPlugin)
# Disable C++11
REMOVE_DEFINITIONS(-std=c++0x)
# Enable C++11 for CXXFLAGS only and not for Windows
IF(NOT LMMS_BUILD_WIN32)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
ENDIF()
BUILD_PLUGIN(ladspaeffect LadspaEffect.cpp LadspaControls.cpp LadspaControlDialog.cpp LadspaSubPluginFeatures.cpp LadspaEffect.h LadspaControls.h LadspaControlDialog.h LadspaSubPluginFeatures.h MOCFILES LadspaEffect.h LadspaControls.h LadspaControlDialog.h EMBEDDED_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.png")

View File

@@ -731,6 +731,7 @@ void lookahead_limiter::process(float &left, float &right, float * multi_buffer)
_peak = fabs(buffer[nextpos[j]]) > fabs(buffer[nextpos[j] + 1]) ? fabs(buffer[nextpos[j]]) : fabs(buffer[nextpos[j] + 1]);
// calc a delta to use to reach our incoming peak from the
// stored position
_peak = std::max( _peak, 0.000001f );
_delta = (_limit / peak - (limit * _multi_coeff * weight) / _peak) / (((buffer_size - nextpos[j] + pos) % buffer_size) / channels);
if(_delta < nextdelta[j]) {
// if the buffered delta is more important than the delta

View File

@@ -28,10 +28,10 @@
02111-1307, USA or point your web browser to http://www.gnu.org.
*/
#include <algorithm>
#include "basics.h"
#include <algorithm>
#include "SweepVF.h"
#include "Descriptor.h"

View File

@@ -836,7 +836,7 @@ static void __attribute__((constructor)) swh_init() {
D_("Release time (s)");
port_range_hints[DYSONCOMPRESS_RELEASE_TIME].HintDescriptor =
LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_LOW;
port_range_hints[DYSONCOMPRESS_RELEASE_TIME].LowerBound = 0;
port_range_hints[DYSONCOMPRESS_RELEASE_TIME].LowerBound = 0.0000001;
port_range_hints[DYSONCOMPRESS_RELEASE_TIME].UpperBound = 1;
/* Parameters for Fast compression ratio */

View File

@@ -73,7 +73,7 @@ typedef struct {
float *op; // pointer to output value
} sv_filter;
inline float soft_clip(float sc_in) {
float soft_clip(float sc_in) {
if ((sc_in < CLIP) && (sc_in > -CLIP)) {
return sc_in;
} else if (sc_in > 0.0f) {
@@ -86,7 +86,7 @@ inline float soft_clip(float sc_in) {
/* Store data in SVF struct, takes the sampling frequency, cutoff frequency
and Q, and fills in the structure passed */
inline void setup_svf(sv_filter *sv, float fs, float fc, float q, int t) {
void setup_svf(sv_filter *sv, float fs, float fc, float q, int t) {
sv->f = 2.0f * sinf(M_PI * fc / (float)(fs * F_R));
sv->q = 2.0f * cosf(powf(q, 0.1f) * M_PI * 0.5f);
sv->qnrm = sqrtf(sv->q*0.5f + 0.01f);
@@ -111,7 +111,7 @@ inline void setup_svf(sv_filter *sv, float fs, float fc, float q, int t) {
/* Change the frequency of a running SVF */
inline void setup_f_svf(sv_filter *sv, const float fs, const float fc) {
void setup_f_svf(sv_filter *sv, const float fs, const float fc) {
sv->f = 2.0f * sin(M_PI * fc / ((float)(fs * F_R)));
}

View File

@@ -115,8 +115,8 @@ static void runShaper(LADSPA_Handle instance, unsigned long sample_count) {
if (shapep < 1.0f && shapep > -1.0f) {
shape = 1.0f;
} else if (shape < 0) {
shape = -1.0f / shape;
} else if (shapep < 0) {
shape = -1.0f / shapep;
} else {
shape = shapep;
}
@@ -160,8 +160,8 @@ static void runAddingShaper(LADSPA_Handle instance, unsigned long sample_count)
if (shapep < 1.0f && shapep > -1.0f) {
shape = 1.0f;
} else if (shape < 0) {
shape = -1.0f / shape;
} else if (shapep < 0) {
shape = -1.0f / shapep;
} else {
shape = shapep;
}

View File

@@ -31,7 +31,7 @@ static void __attribute__((constructor)) swh_init(); // forward declaration
#define MAX_BSIZE 1000
inline int partition(LADSPA_Data array[], int left, int right);
int partition(LADSPA_Data array[], int left, int right);
void q_sort(LADSPA_Data array[], int left, int right) {
float pivot = partition(array, left, right);
@@ -44,7 +44,7 @@ void q_sort(LADSPA_Data array[], int left, int right) {
}
}
inline int partition(LADSPA_Data array[], int left, int right) {
int partition(LADSPA_Data array[], int left, int right) {
float pivot = array[left];
while (left < right) {

View File

@@ -35,7 +35,7 @@ waveguide_nl *waveguide_nl_new(int size, float fc, float da, float db)
return wg;
}
inline void waveguide_nl_reset(waveguide_nl *wg)
void waveguide_nl_reset(waveguide_nl *wg)
{
memset(wg->buffer[0], 0, wg->size * sizeof(float));
memset(wg->buffer[1], 0, wg->size * sizeof(float));
@@ -45,7 +45,7 @@ inline void waveguide_nl_reset(waveguide_nl *wg)
wg->zm1[1] = 0.0f;
}
inline void waveguide_nl_free(waveguide_nl *wg)
void waveguide_nl_free(waveguide_nl *wg)
{
if (!wg) {
return;
@@ -55,7 +55,7 @@ inline void waveguide_nl_free(waveguide_nl *wg)
free(wg);
}
inline void waveguide_nl_set_delay(waveguide_nl *wg, int delay)
void waveguide_nl_set_delay(waveguide_nl *wg, int delay)
{
if (delay > wg->size) {
wg->delay = wg->size;
@@ -66,18 +66,18 @@ inline void waveguide_nl_set_delay(waveguide_nl *wg, int delay)
}
}
inline void waveguide_nl_set_fc(waveguide_nl *wg, float fc)
void waveguide_nl_set_fc(waveguide_nl *wg, float fc)
{
wg->fc = fc;
}
inline void waveguide_nl_set_ap(waveguide_nl *wg, float da, float db)
void waveguide_nl_set_ap(waveguide_nl *wg, float da, float db)
{
wg->a1a = (1.0f - da) / (1.0f + da);
wg->a1b = (1.0f - db) / (1.0f + db);
}
inline void waveguide_nl_process_lin(waveguide_nl *wg, float in0, float in1, float *out0, float *out1)
void waveguide_nl_process_lin(waveguide_nl *wg, float in0, float in1, float *out0, float *out1)
{
float tmp;
@@ -103,7 +103,7 @@ inline void waveguide_nl_process_lin(waveguide_nl *wg, float in0, float in1, flo
}
}
inline void waveguide_nl_process(waveguide_nl *wg, float in0, float in1, float *out0, float *out1)
void waveguide_nl_process(waveguide_nl *wg, float in0, float in1, float *out0, float *out1)
{
float tmp;
float a1;

View File

@@ -47,7 +47,7 @@ struct bandpasses
LADSPA_Data y[MAX_BANDS];
};
void inline doBandpasses(struct bandpasses *bands, LADSPA_Data sample, int num_bands);
void doBandpasses(struct bandpasses *bands, LADSPA_Data sample, int num_bands);
struct bands_out{
LADSPA_Data decay[MAX_BANDS];
@@ -65,7 +65,7 @@ const LADSPA_Data decay_table[] =
1/250.0, 1/250.0, 1/250.0
};
void inline doBandpasses(struct bandpasses *bands, LADSPA_Data sample, int num_bands)
void doBandpasses(struct bandpasses *bands, LADSPA_Data sample, int num_bands)
{
int i;
for (i=0; i < num_bands; i++)

View File

@@ -55,7 +55,6 @@ Plugin::Descriptor PLUGIN_EXPORT vsteffect_plugin_descriptor =
VstEffect::VstEffect( Model * _parent,
const Descriptor::SubPluginFeatures::Key * _key ) :
Effect( &vsteffect_plugin_descriptor, _parent, _key ),
m_plugin( NULL ),
m_pluginMutex(),
m_key( *_key ),
m_vstControls( this )
@@ -73,7 +72,6 @@ VstEffect::VstEffect( Model * _parent,
VstEffect::~VstEffect()
{
closePlugin();
}
@@ -128,22 +126,20 @@ void VstEffect::openPlugin( const QString & _plugin )
VstPlugin::tr( "Loading plugin" ),
VstPlugin::tr( "Please wait while loading VST plugin..." ),
PLUGIN_NAME::getIconPixmap( "logo", 24, 24 ), 0 );
m_pluginMutex.lock();
m_plugin = new VstPlugin( _plugin );
QMutexLocker ml( &m_pluginMutex ); Q_UNUSED( ml );
m_plugin = QSharedPointer<VstPlugin>(new VstPlugin( _plugin ));
if( m_plugin->failed() )
{
m_pluginMutex.unlock();
closePlugin();
m_plugin.clear();
delete tf;
collectErrorForUI( VstPlugin::tr( "The VST plugin %1 could not be loaded." ).arg( _plugin ) );
return;
}
VstPlugin::connect( Engine::getSong(), SIGNAL( tempoChanged( bpm_t ) ), m_plugin, SLOT( setTempo( bpm_t ) ) );
VstPlugin::connect( Engine::getSong(), SIGNAL( tempoChanged( bpm_t ) ), m_plugin.data(), SLOT( setTempo( bpm_t ) ) );
m_plugin->setTempo( Engine::getSong()->getTempo() );
m_pluginMutex.unlock();
delete tf;
m_key.attributes["file"] = _plugin;
@@ -151,21 +147,6 @@ void VstEffect::openPlugin( const QString & _plugin )
void VstEffect::closePlugin()
{
m_pluginMutex.lock();
if( m_plugin && m_plugin->pluginWidget() != NULL )
{
delete m_plugin->pluginWidget();
}
delete m_plugin;
m_plugin = NULL;
m_pluginMutex.unlock();
}
extern "C"
{

View File

@@ -25,13 +25,14 @@
#ifndef _VST_EFFECT_H
#define _VST_EFFECT_H
#include <QMutex>
#include <QtCore/QMutex>
#include <QtCore/QSharedPointer>
#include "Effect.h"
#include "VstPlugin.h"
#include "VstEffectControlDialog.h"
#include "VstEffectControls.h"
class VstPlugin;
class VstEffect : public Effect
{
@@ -58,7 +59,7 @@ private:
void openPlugin( const QString & _plugin );
void closePlugin();
VstPlugin * m_plugin;
QSharedPointer<VstPlugin> m_plugin;
QMutex m_pluginMutex;
EffectKey m_key;

View File

@@ -30,6 +30,7 @@
#include "VstEffectControlDialog.h"
#include "VstEffect.h"
#include "ConfigManager.h"
#include "PixmapButton.h"
#include "embed.h"
#include "ToolTip.h"
@@ -52,32 +53,43 @@ VstEffectControlDialog::VstEffectControlDialog( VstEffectControls * _ctl ) :
l->setVerticalSpacing( 2 );
l->setHorizontalSpacing( 2 );
bool embed_vst = false;
if( _ctl != NULL && _ctl->m_effect != NULL &&
_ctl->m_effect->m_plugin != NULL )
{
m_plugin = _ctl->m_effect->m_plugin;
m_plugin->showEditor( NULL, true );
m_pluginWidget = m_plugin->pluginWidget();
embed_vst = m_plugin->embedMethod() != "none";
if (embed_vst) {
m_plugin->createUI( nullptr, true );
m_pluginWidget = m_plugin->pluginWidget( false );
#ifdef LMMS_BUILD_WIN32
if( !m_pluginWidget )
{
m_pluginWidget = m_plugin->pluginWidget( false );
}
if( !m_pluginWidget )
{
m_pluginWidget = m_plugin->pluginWidget( false );
}
#endif
}
}
if( m_pluginWidget )
if ( m_plugin && (!embed_vst || m_pluginWidget) )
{
setWindowTitle( m_pluginWidget->windowTitle() );
setMinimumWidth( 250 );
setWindowTitle( m_plugin->name() );
QPushButton * btn = new QPushButton( tr( "Show/hide" ) );
btn->setCheckable( true );
connect( btn, SIGNAL( toggled( bool ) ),
m_pluginWidget, SLOT( setVisible( bool ) ) );
emit btn->click();
if (embed_vst) {
btn->setCheckable( true );
btn->setChecked( true );
connect( btn, SIGNAL( toggled( bool ) ),
SLOT( togglePluginUI( bool ) ) );
} else {
connect( btn, SIGNAL( clicked( bool ) ),
SLOT( togglePluginUI( bool ) ) );
}
btn->setMinimumWidth( 78 );
btn->setMaximumWidth( 78 );
@@ -206,8 +218,13 @@ VstEffectControlDialog::VstEffectControlDialog( VstEffectControls * _ctl ) :
m_savePresetButton->setMinimumHeight( 21 );
m_savePresetButton->setMaximumHeight( 21 );
int newSize = m_pluginWidget->width() + 20;
newSize = (newSize < 250) ? 250 : newSize;
int newSize = 0;
if (embed_vst) {
newSize = m_pluginWidget->width() + 20;
}
newSize = std::max(newSize, 250);
QWidget* resize = new QWidget(this);
resize->resize( newSize, 10 );
QWidget* space0 = new QWidget(this);
@@ -219,7 +236,9 @@ VstEffectControlDialog::VstEffectControlDialog( VstEffectControls * _ctl ) :
l->addItem( new QSpacerItem( newSize - 20, 30, QSizePolicy::Fixed,
QSizePolicy::Fixed ), 1, 0 );
l->addWidget( resize, 2, 0, 1, 1, Qt::AlignCenter );
l->addWidget( m_pluginWidget, 3, 0, 1, 1, Qt::AlignCenter );
if (embed_vst) {
l->addWidget( m_pluginWidget, 3, 0, 1, 1, Qt::AlignCenter );
}
l->setRowStretch( 5, 1 );
l->setColumnStretch( 1, 1 );
@@ -264,3 +283,15 @@ VstEffectControlDialog::~VstEffectControlDialog()
//delete m_pluginWidget;
}
void VstEffectControlDialog::togglePluginUI( bool checked )
{
if( !m_plugin ) {
return;
}
m_plugin->toggleUI();
}

View File

@@ -31,6 +31,7 @@
#include <QObject>
#include <QPainter>
#include <QLabel>
#include <QSharedPointer>
class VstEffectControls;
@@ -59,9 +60,12 @@ private:
PixmapButton * m_managePluginButton;
PixmapButton * m_savePresetButton;
VstPlugin * m_plugin;
QSharedPointer<VstPlugin> m_plugin;
QLabel * tbLabel;
private slots:
void togglePluginUI( bool checked );
} ;
#endif

View File

@@ -36,6 +36,7 @@
#include <QApplication>
#include <QFileDialog>
#include <QFileInfo>
#include <QPushButton>
#include <QTimerEvent>
#include <QVBoxLayout>
@@ -150,15 +151,22 @@ CarlaInstrument::CarlaInstrument(InstrumentTrack* const instrumentTrack, const D
fHost.uiName = NULL;
fHost.uiParentId = 0;
// figure out prefix from dll filename
// carla/resources contains PyQt scripts required for launch
QString dllName(carla_get_library_filename());
QString resourcesPath;
#if defined(CARLA_OS_LINUX)
fHost.resourceDir = strdup(QString(dllName.split("/lib/carla")[0] + "/share/carla/resources/").toUtf8().constData());
#else
fHost.resourceDir = NULL;
// parse prefix from dll filename
QDir path = QFileInfo(dllName).dir();
path.cdUp();
path.cdUp();
resourcesPath = path.absolutePath() + "/share/carla/resources";
#elif defined(CARLA_OS_MAC)
// assume standard install location
resourcesPath = "/Applications/Carla.app/Contents/MacOS/resources";
#elif defined(CARLA_OS_WIN32) || defined(CARLA_OS_WIN64)
// not yet supported
#endif
fHost.resourceDir = strdup(resourcesPath.toUtf8().constData());
fHost.get_buffer_size = host_get_buffer_size;
fHost.get_sample_rate = host_get_sample_rate;
fHost.is_offline = host_is_offline;
@@ -252,21 +260,14 @@ intptr_t CarlaInstrument::handleDispatcher(const NativeHostDispatcherOpcode opco
switch (opcode)
{
case NATIVE_HOST_OPCODE_NULL:
break;
case NATIVE_HOST_OPCODE_UPDATE_PARAMETER:
case NATIVE_HOST_OPCODE_UPDATE_MIDI_PROGRAM:
case NATIVE_HOST_OPCODE_RELOAD_PARAMETERS:
case NATIVE_HOST_OPCODE_RELOAD_MIDI_PROGRAMS:
case NATIVE_HOST_OPCODE_RELOAD_ALL:
// nothing
break;
case NATIVE_HOST_OPCODE_UI_UNAVAILABLE:
handleUiClosed();
break;
case NATIVE_HOST_OPCODE_HOST_IDLE:
qApp->processEvents();
break;
default:
break;
}
return ret;

View File

@@ -25,6 +25,8 @@
#ifndef CARLA_H
#define CARLA_H
#include <QtCore/QMutex>
#include "CarlaNative.h"
#include "Instrument.h"

View File

@@ -339,7 +339,6 @@ lb302Synth::lb302Synth( InstrumentTrack * _instrumentTrack ) :
// Experimenting with a0 between original (0.5) and 1.0
vca_a0 = 0.5;
vca_a = 9;
vca_mode = 3;
vcfs[0] = new lb302FilterIIR2(&fs);

View File

@@ -1692,6 +1692,8 @@ QWidget * MonstroView::setupOperatorsView( QWidget * _parent )
makeknob( m_osc3SpoKnob, KNOBCOL4, O3ROW, tr( "Stereo phase offset" ), tr( " deg" ), "osc3Knob" )
makeknob( m_osc3SubKnob, KNOBCOL5, O3ROW, tr( "Sub-osc mix" ), "", "osc3Knob" )
m_osc3VolKnob -> setVolumeKnob( true );
m_osc3Wave1Box = new ComboBox( view );
m_osc3Wave1Box -> setGeometry( 160, O3ROW + 7, 42, 22 );
m_osc3Wave1Box->setFont( pointSize<8>( m_osc3Wave1Box->font() ) );

View File

@@ -1,6 +1,3 @@
INCLUDE(BuildPlugin)
# Disable C++11
REMOVE_DEFINITIONS(-std=c++0x)
BUILD_PLUGIN(papu papu_instrument.cpp papu_instrument.h Basic_Gb_Apu.cpp Basic_Gb_Apu.h gb_apu/Gb_Oscs.cpp gb_apu/Gb_Apu.h gb_apu/Blip_Buffer.cpp gb_apu/Gb_Apu.cpp gb_apu/Gb_Oscs.h gb_apu/blargg_common.h gb_apu/Blip_Buffer.h gb_apu/Multi_Buffer.cpp gb_apu/blargg_source.h gb_apu/Multi_Buffer.h MOCFILES papu_instrument.h EMBEDDED_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.png")

View File

@@ -464,6 +464,7 @@ void sfxrInstrument::playNote( NotePlayHandle * _n, sampleFrame * _working_buffe
}
else if( static_cast<SfxrSynth*>(_n->m_pluginData)->isPlaying() == false )
{
memset(_working_buffer + offset, 0, sizeof(sampleFrame) * frameNum);
_n->noteOff();
return;
}

View File

@@ -32,6 +32,7 @@
#include <QMenu>
#include <QDomElement>
#include "ConfigManager.h"
#include "BufferManager.h"
#include "Engine.h"
#include "gui_templates.h"
@@ -89,6 +90,10 @@ vestigeInstrument::vestigeInstrument( InstrumentTrack * _instrument_track ) :
// now we need a play-handle which cares for calling play()
InstrumentPlayHandle * iph = new InstrumentPlayHandle( this, _instrument_track );
Engine::mixer()->addPlayHandle( iph );
connect( ConfigManager::inst(), SIGNAL( valueChanged(QString,QString,QString) ),
this, SLOT( handleConfigChange(QString, QString, QString) ),
Qt::QueuedConnection );
}
@@ -170,6 +175,22 @@ void vestigeInstrument::setParameter( void )
}
}
void vestigeInstrument::handleConfigChange(QString cls, QString attr, QString value)
{
Q_UNUSED(cls); Q_UNUSED(attr); Q_UNUSED(value);
// Disabled for consistency with VST effects that don't implement this. (#3786)
// if ( cls == "ui" && attr == "vstembedmethod" )
// {
// reloadPlugin();
// }
}
void vestigeInstrument::reloadPlugin()
{
closePlugin();
loadFile( m_pluginDLL );
}
@@ -262,7 +283,7 @@ void vestigeInstrument::loadFile( const QString & _file )
return;
}
m_plugin->showEditor( NULL, false );
m_plugin->showUI();
if( set_ch_name )
{
@@ -366,10 +387,6 @@ void vestigeInstrument::closePlugin( void )
}
m_pluginMutex.lock();
if( m_plugin )
{
delete m_plugin->pluginWidget();
}
delete m_plugin;
m_plugin = NULL;
m_pluginMutex.unlock();
@@ -739,19 +756,7 @@ void VestigeInstrumentView::toggleGUI( void )
{
return;
}
QWidget * w = m_vi->m_plugin->pluginWidget();
if( w == NULL )
{
return;
}
if( w->isHidden() )
{
w->show();
}
else
{
w->hide();
}
m_vi->m_plugin->toggleUI();
}

View File

@@ -74,6 +74,8 @@ public:
protected slots:
void setParameter( void );
void handleConfigChange( QString cls, QString attr, QString value );
void reloadPlugin();
private:
void closePlugin( void );

View File

@@ -29,34 +29,63 @@ SET(REMOTE_VST_PLUGIN_FILEPATH "RemoteVstPlugin" CACHE STRING "Relative file pat
ADD_DEFINITIONS(-DREMOTE_VST_PLUGIN_FILEPATH="${REMOTE_VST_PLUGIN_FILEPATH}")
BUILD_PLUGIN(vstbase vst_base.cpp VstPlugin.cpp VstPlugin.h communication.h MOCFILES VstPlugin.h)
IF(LMMS_BUILD_LINUX AND WANT_QT5)
TARGET_LINK_LIBRARIES(vstbase qx11embedcontainer)
ENDIF()
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)
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 -L/usr/lib/i386-linux-gnu/wine/ -luser32 -lkernel32 -lgdi32)
ENDIF()
#The following check works on Fedora systems
IF("${WINEBUILD_OUTPUT}" MATCHES ".*lib64/wine/libwinecrt0.a.*")
SET(EXTRA_FLAGS ${EXTRA_FLAGS} -nodefaultlibs /usr/lib/i386/wine/libwinecrt0.a -luser32 -lkernel32 -lgdi32)
IF(WINE_LIBRARY_FIX)
SET(EXTRA_FLAGS ${EXTRA_FLAGS} -nodefaultlibs ${WINE_LIBRARY_FIX}wine/libwinecrt0.a -L${WINE_LIBRARY_FIX}wine/ -luser32 -lkernel32 -lgdi32)
ENDIF()
ENDIF(LMMS_HOST_X86_64)
SET(WINE_CXX_FLAGS "" CACHE STRING "Extra flags passed to wineg++")
STRING(REPLACE "include/wine" "include" WINE_INCLUDE_BASE_DIR ${WINE_INCLUDE_DIR})
STRING(REPLACE "lib/libwine.so" "lib" WINE_LIBRARY_DIR ${WINE_LIBRARY})
STRING(REPLACE " " ";" WINE_BUILD_FLAGS ${CMAKE_CXX_FLAGS} " " ${CMAKE_EXE_LINKER_FLAGS} " " ${WINE_CXX_FLAGS})
SET(WINE_CXX_ARGS
-I${CMAKE_BINARY_DIR}
-I${CMAKE_SOURCE_DIR}/include
-I${WINE_INCLUDE_BASE_DIR}
-L${WINE_LIBRARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/RemoteVstPlugin.cpp
-std=c++0x
-mwindows -lpthread ${EXTRA_FLAGS} -fno-omit-frame-pointer
${WINE_BUILD_FLAGS}
-o ../RemoteVstPlugin
)
# winegcc fails if winebuild is not in path
GET_FILENAME_COMPONENT(WINE_BINDIR ${WINE_CXX} PATH)
FIND_PROGRAM(WINEBUILD winebuild NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH)
IF(NOT WINEBUILD)
IF(CMAKE_VERSION VERSION_LESS 3.1)
MESSAGE(WARNING "winebuild is not in PATH. Building RemoteVstPlugin may fail.")
ELSE()
SET(WINE_CXX_ARGS -E env PATH=$ENV{PATH}:${WINE_BINDIR} ${WINE_CXX} ${WINE_CXX_ARGS})
SET(WINE_CXX "${CMAKE_COMMAND}")
ENDIF()
ENDIF()
set(ENV{PATH} "$ENV{PATH}:${WINE_BINDIR}")
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/usr/include/wine/windows ${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
)
SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/RemoteVstPlugin.cpp"
COMMAND export
ARGS "PATH=$PATH:${WINE_BINDIR}"
COMMAND ${WINE_CXX}
ARGS ${WINE_CXX_ARGS}
# Ensure correct file extension
COMMAND sh -c "mv ../RemoteVstPlugin.exe ../RemoteVstPlugin || true"
TARGET vstbase
OUTPUTS ../RemoteVstPlugin
VERBATIM
)
SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES ../RemoteVstPlugin.exe.so)
INSTALL(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/../RemoteVstPlugin" "${CMAKE_CURRENT_BINARY_DIR}/../RemoteVstPlugin.exe.so" DESTINATION "${PLUGIN_DIR}")

View File

@@ -63,17 +63,10 @@
#define USE_WS_PREFIX
#include <windows.h>
#if defined(LMMS_BUILD_WIN32) || defined(LMMS_BUILD_WIN64)
#include "basename.c"
#else
#include <libgen.h>
#endif
#include <vector>
#include <queue>
#include <string>
#include <iostream>
#include <aeffectx.h>
@@ -105,14 +98,18 @@ struct ERect
#ifndef USE_QT_SHMEM
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#endif
using namespace std;
static VstHostLanguages hlang = LanguageEnglish;
static bool EMBED = false;
static bool EMBED_X11 = false;
static bool EMBED_WIN32 = false;
class RemoteVstPlugin;
@@ -136,6 +133,7 @@ public:
void init( const std::string & _plugin_file );
void initEditor();
void destroyEditor();
virtual void process( const sampleFrame * _in, sampleFrame * _out );
@@ -356,6 +354,7 @@ private:
int m_windowHeight;
bool m_initialized;
bool m_registeredWindowClass;
pthread_mutex_t m_pluginLock;
bool m_processing;
@@ -401,7 +400,6 @@ RemoteVstPlugin::RemoteVstPlugin( key_t _shm_in, key_t _shm_out ) :
RemoteVstPlugin::RemoteVstPlugin( const char * socketPath ) :
RemotePluginClient( socketPath ),
#endif
m_shortName( "" ),
m_libInst( NULL ),
m_plugin( NULL ),
m_window( NULL ),
@@ -409,6 +407,7 @@ RemoteVstPlugin::RemoteVstPlugin( const char * socketPath ) :
m_windowWidth( 0 ),
m_windowHeight( 0 ),
m_initialized( false ),
m_registeredWindowClass( false ),
m_pluginLock(),
m_processing( false ),
m_messageList(),
@@ -424,7 +423,6 @@ RemoteVstPlugin::RemoteVstPlugin( const char * socketPath ) :
m_in( NULL ),
m_shmID( -1 ),
m_vstSyncData( NULL )
{
pthread_mutex_init( &m_pluginLock, NULL );
pthread_mutex_init( &m_shmLock, NULL );
@@ -491,14 +489,7 @@ RemoteVstPlugin::RemoteVstPlugin( const char * socketPath ) :
RemoteVstPlugin::~RemoteVstPlugin()
{
if( m_window != NULL )
{
pluginDispatch( effEditClose );
#ifdef LMMS_BUILD_LINUX
CloseWindow( m_window );
#endif
m_window = NULL;
}
destroyEditor();
pluginDispatch( effMainsChanged, 0, 0 );
pluginDispatch( effClose );
#ifndef USE_QT_SHMEM
@@ -535,22 +526,48 @@ RemoteVstPlugin::~RemoteVstPlugin()
bool RemoteVstPlugin::processMessage( const message & _m )
{
if (! EMBED)
{
switch( _m.id )
{
case IdShowUI:
initEditor();
return true;
case IdHideUI:
destroyEditor();
return true;
case IdToggleUI:
if( m_window )
{
destroyEditor();
}
else
{
initEditor();
}
return true;
case IdIsUIVisible:
sendMessage( message( IdIsUIVisible )
.addInt( m_window ? 1 : 0 ) );
return true;
}
}
else if (EMBED && _m.id == IdShowUI)
{
ShowWindow( m_window, SW_SHOWNORMAL );
UpdateWindow( m_window );
return true;
}
switch( _m.id )
{
case IdVstLoadPlugin:
init( _m.getString() );
break;
#ifdef LMMS_BUILD_WIN32
case IdVstPluginWindowInformation:
{
HWND top = FindWindowEx( NULL, NULL, NULL,
_m.getString().c_str() );
m_window = FindWindowEx( top, NULL, NULL, NULL );
break;
}
#endif
case IdVstSetTempo:
setBPM( _m.getInt() );
break;
@@ -688,9 +705,20 @@ void RemoteVstPlugin::init( const std::string & _plugin_file )
static void close_check( int fd )
{
if( close( fd ) )
{
perror( "close" );
}
}
void RemoteVstPlugin::initEditor()
{
if( !( m_plugin->flags & effFlagsHasEditor ) )
if( m_window || !( m_plugin->flags & effFlagsHasEditor ) )
{
return;
}
@@ -704,38 +732,37 @@ void RemoteVstPlugin::initEditor()
}
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = DefWindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.hIcon = LoadIcon( NULL, IDI_APPLICATION );
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hbrBackground = (HBRUSH) GetStockObject( BLACK_BRUSH );
wc.lpszMenuName = NULL;
wc.lpszClassName = "LVSL";
if( !RegisterClass( &wc ) )
if( !m_registeredWindowClass )
{
return;
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = DefWindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.hIcon = LoadIcon( NULL, IDI_APPLICATION );
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = "LVSL";
if( !RegisterClass( &wc ) )
{
return;
}
m_registeredWindowClass = true;
}
#ifdef LMMS_BUILD_LINUX
//m_window = CreateWindowEx( 0, "LVSL", m_shortName.c_str(),
// ( WS_OVERLAPPEDWINDOW | WS_THICKFRAME ) & ~WS_MAXIMIZEBOX,
// 0, 0, 10, 10, NULL, NULL, hInst, NULL );
DWORD dwStyle;
if (EMBED) {
dwStyle = WS_POPUP | WS_SYSMENU | WS_BORDER;
} else {
dwStyle = WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX;
}
m_window = CreateWindowEx( 0 , "LVSL", m_shortName.c_str(),
WS_POPUP | WS_SYSMENU | WS_BORDER , 0, 0, 10, 10, NULL, NULL, hInst, NULL);
#else
m_windowID = 1; // arbitrary value on win32 to signal
// vstPlugin-class that we have an editor
m_window = CreateWindowEx( 0, "LVSL", m_shortName.c_str(),
WS_CHILD, 0, 0, 10, 10,
m_window, NULL, hInst, NULL );
#endif
m_window = CreateWindowEx( 0, "LVSL", pluginName(),
dwStyle,
0, 0, 10, 10, NULL, NULL, hInst, NULL );
if( m_window == NULL )
{
debugMessage( "initEditor(): cannot create editor window\n" );
@@ -756,17 +783,37 @@ void RemoteVstPlugin::initEditor()
SWP_NOMOVE | SWP_NOZORDER );
pluginDispatch( effEditTop );
ShowWindow( m_window, SW_SHOWNORMAL );
UpdateWindow( m_window );
if (! EMBED) {
ShowWindow( m_window, SW_SHOWNORMAL );
}
#ifdef LMMS_BUILD_LINUX
m_windowID = (intptr_t) GetProp( m_window, "__wine_x11_whole_window" );
#else
// 64-bit versions of Windows use 32-bit handles for interoperability
m_windowID = (intptr_t) m_window;
#endif
}
void RemoteVstPlugin::destroyEditor()
{
if( m_window == NULL )
{
return;
}
pluginDispatch( effEditClose );
// Destroying the window takes some time in Wine 1.8.5
DestroyWindow( m_window );
m_window = NULL;
}
bool RemoteVstPlugin::load( const std::string & _plugin_file )
{
if( ( m_libInst = LoadLibrary( _plugin_file.c_str() ) ) == NULL )
@@ -779,10 +826,6 @@ bool RemoteVstPlugin::load( const std::string & _plugin_file )
return false;
}
char * tmp = strdup( _plugin_file.c_str() );
m_shortName = basename( tmp );
free( tmp );
typedef AEffect * ( __stdcall * mainEntryPointer )
( audioMasterCallback );
mainEntryPointer mainEntry = (mainEntryPointer)
@@ -1067,7 +1110,7 @@ void RemoteVstPlugin::saveChunkToFile( const std::string & _file )
fprintf( stderr,
"Error saving chunk to file.\n" );
}
close( fd );
close_check( fd );
}
}
}
@@ -1392,7 +1435,7 @@ void RemoteVstPlugin::loadChunkFromFile( const std::string & _file, int _len )
{
fprintf( stderr, "Error loading chunk from file.\n" );
}
close( fd );
close_check( fd );
pluginDispatch( effSetChunk, 0, _len, chunk );
@@ -1970,6 +2013,12 @@ LRESULT CALLBACK RemoteVstPlugin::messageWndProc( HWND hwnd, UINT uMsg,
break;
}
}
else if( uMsg == WM_SYSCOMMAND && wParam == SC_CLOSE )
{
__plugin->destroyEditor();
return 0;
}
return DefWindowProc( hwnd, uMsg, wParam, lParam );
}
@@ -1979,9 +2028,9 @@ LRESULT CALLBACK RemoteVstPlugin::messageWndProc( HWND hwnd, UINT uMsg,
int main( int _argc, char * * _argv )
{
#ifdef SYNC_WITH_SHM_FIFO
if( _argc < 3 )
if( _argc < 4 )
#else
if( _argc < 2 )
if( _argc < 3 )
#endif
{
fprintf( stderr, "not enough arguments\n" );
@@ -2013,6 +2062,41 @@ int main( int _argc, char * * _argv )
}
#endif
{
#ifdef SYNC_WITH_SHM_FIFO
int embedMethodIndex = 3;
#else
int embedMethodIndex = 2;
#endif
std::string embedMethod = _argv[embedMethodIndex];
if ( embedMethod == "none" )
{
cerr << "Starting detached." << endl;
EMBED = EMBED_X11 = EMBED_WIN32 = false;
}
else if ( embedMethod == "win32" )
{
cerr << "Starting using Win32-native embedding." << endl;
EMBED = EMBED_WIN32 = true; EMBED_X11= false;
}
else if ( embedMethod == "qt" )
{
cerr << "Starting using Qt-native embedding." << endl;
EMBED = true; EMBED_X11 = EMBED_WIN32 = false;
}
else if ( embedMethod == "xembed" )
{
cerr << "Starting using X11Embed protocol." << endl;
EMBED = EMBED_X11 = true; EMBED_WIN32 = false;
}
else
{
cerr << "Unknown embed method " << embedMethod << ". Starting detached instead." << endl;
EMBED = EMBED_X11 = EMBED_WIN32 = false;
}
}
// constructor automatically will process messages until it receives
// a IdVstLoadPlugin message and processes it
#ifdef SYNC_WITH_SHM_FIFO

View File

@@ -2,7 +2,7 @@
* VstPlugin.cpp - implementation of VstPlugin class
*
* Copyright (c) 2005-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
*
* This file is part of LMMS - https://lmms.io
*
* This program is free software; you can redistribute it and/or
@@ -24,6 +24,7 @@
#include "VstPlugin.h"
#include <QtCore/QDebug>
#include <QDir>
#include <QFileInfo>
#include <QLocale>
@@ -31,18 +32,26 @@
#include <QCloseEvent>
#include <QMdiArea>
#include <QMdiSubWindow>
#ifdef LMMS_BUILD_LINUX
#if QT_VERSION < 0x050000
#include <QX11EmbedContainer>
#include <QX11Info>
# if QT_VERSION < 0x050000
# include <QX11EmbedContainer>
# include <QX11Info>
# else
# include "X11EmbedContainer.h"
# include <QWindow>
# endif
#endif
#else
#include <QLayout>
#if QT_VERSION >= 0x050000
# include <QWindow>
#endif
#include <QDomDocument>
#ifdef LMMS_BUILD_WIN32
#include <windows.h>
# include <windows.h>
# include <QLayout>
#endif
#include "ConfigManager.h"
@@ -52,8 +61,6 @@
#include "Song.h"
#include "templates.h"
#include "FileDialog.h"
#include <QLayout>
class vstSubWin : public QMdiSubWindow
{
@@ -78,24 +85,13 @@ public:
} ;
VstPlugin::VstPlugin( const QString & _plugin ) :
RemotePlugin(),
JournallingObject(),
m_plugin( _plugin ),
m_pluginWidget( NULL ),
m_pluginWindowID( 0 ),
m_embedMethod( ConfigManager::inst()->vstEmbedMethod() ),
m_badDllFormat( false ),
m_name(),
m_version( 0 ),
m_vendorString(),
m_productString(),
m_currentProgramName(),
m_allProgramNames(),
p_name(),
m_currentProgram(),
m_idleTimer()
m_currentProgram()
{
setSplittedChannels( true );
@@ -126,6 +122,8 @@ VstPlugin::VstPlugin( const QString & _plugin ) :
VstPlugin::~VstPlugin()
{
delete m_pluginSubWindow;
delete m_pluginWidget;
}
@@ -133,29 +131,15 @@ VstPlugin::~VstPlugin()
void VstPlugin::tryLoad( const QString &remoteVstPluginExecutable )
{
init( remoteVstPluginExecutable, false );
init( remoteVstPluginExecutable, false, {m_embedMethod} );
waitForHostInfoGotten();
if( failed() )
{
return;
}
lock();
#ifdef LMMS_BUILD_WIN32
QWidget * helper = new QWidget;
QHBoxLayout * l = new QHBoxLayout( helper );
QWidget * target = new QWidget( helper );
l->setSpacing( 0 );
l->setMargin( 0 );
l->addWidget( target );
static int k = 0;
const QString t = QString( "vst%1%2" ).arg( GetCurrentProcessId()<<10 ).
arg( ++k );
helper->setWindowTitle( t );
// we've to call that for making sure, Qt created the windows
(void) helper->winId();
(void) target->winId();
sendMessage( message( IdVstPluginWindowInformation ).
addString( QSTR_TO_STDSTR( t ) ) );
#endif
VstHostLanguages hlang = LanguageEnglish;
switch( QLocale::system().language() )
@@ -183,95 +167,6 @@ void VstPlugin::tryLoad( const QString &remoteVstPluginExecutable )
waitForInitDone();
unlock();
#ifdef LMMS_BUILD_WIN32
if( !failed() && m_pluginWindowID )
{
target->setFixedSize( m_pluginGeometry );
vstSubWin * sw = new vstSubWin(
gui->mainWindow()->workspace() );
sw->setWidget( helper );
helper->setWindowTitle( name() );
m_pluginWidget = helper;
}
else
{
delete helper;
}
#endif
}
void VstPlugin::showEditor( QWidget * _parent, bool isEffect )
{
QWidget * w = pluginWidget();
if( w )
{
#ifdef LMMS_BUILD_WIN32
// hide sw, plugin window wrapper on win32
// this is obtained from pluginWidget()
if( isEffect )
{
w->setWindowFlags( Qt::FramelessWindowHint );
w->setAttribute( Qt::WA_TranslucentBackground );
}
else
{
w->setWindowFlags( Qt::WindowCloseButtonHint );
}
#endif
w->show();
return;
}
#ifdef LMMS_BUILD_LINUX
if( m_pluginWindowID == 0 )
{
return;
}
m_pluginWidget = new QWidget( _parent );
m_pluginWidget->setFixedSize( m_pluginGeometry );
m_pluginWidget->setWindowTitle( name() );
if( _parent == NULL )
{
vstSubWin * sw = new vstSubWin(
gui->mainWindow()->workspace() );
if( isEffect )
{
sw->setAttribute( Qt::WA_TranslucentBackground );
sw->setWindowFlags( Qt::FramelessWindowHint );
sw->setWidget( m_pluginWidget );
#if QT_VERSION < 0x050000
QX11EmbedContainer * xe = new QX11EmbedContainer( sw );
xe->embedClient( m_pluginWindowID );
xe->setFixedSize( m_pluginGeometry );
xe->show();
#endif
}
else
{
sw->setWindowFlags( Qt::WindowCloseButtonHint );
sw->setWidget( m_pluginWidget );
#if QT_VERSION < 0x050000
QX11EmbedContainer * xe = new QX11EmbedContainer( sw );
xe->embedClient( m_pluginWindowID );
xe->setFixedSize( m_pluginGeometry );
xe->move( 4, 24 );
xe->show();
#endif
}
}
#endif
if( m_pluginWidget )
{
m_pluginWidget->show();
}
}
@@ -289,18 +184,27 @@ void VstPlugin::hideEditor()
void VstPlugin::toggleEditor()
{
QWidget * w = pluginWidget();
if( w )
{
w->setVisible( !w->isVisible() );
}
}
void VstPlugin::loadSettings( const QDomElement & _this )
{
if( pluginWidget() != NULL )
if( _this.attribute( "guivisible" ).toInt() )
{
if( _this.attribute( "guivisible" ).toInt() )
{
showEditor( NULL, false );
}
else
{
hideEditor();
}
showUI();
}
else
{
hideUI();
}
const int num_params = _this.attribute( "numparams" ).toInt();
@@ -334,9 +238,20 @@ void VstPlugin::loadSettings( const QDomElement & _this )
void VstPlugin::saveSettings( QDomDocument & _doc, QDomElement & _this )
{
if( pluginWidget() != NULL )
if ( m_embedMethod != "none" )
{
_this.setAttribute( "guivisible", pluginWidget()->isVisible() );
if( pluginWidget() != NULL )
{
_this.setAttribute( "guivisible", pluginWidget()->isVisible() );
}
}
else
{
int visible = isUIVisible();
if ( visible != -1 )
{
_this.setAttribute( "guivisible", visible );
}
}
// try to save all settings in a chunk
@@ -361,6 +276,18 @@ void VstPlugin::saveSettings( QDomDocument & _doc, QDomElement & _this )
_this.setAttribute( "program", currentProgram() );
}
void VstPlugin::toggleUI()
{
if ( m_embedMethod == "none" )
{
RemotePlugin::toggleUI();
}
else if (pluginWidget())
{
toggleEditor();
}
}
@@ -432,6 +359,23 @@ void VstPlugin::setParameterDump( const QMap<QString, QString> & _pdump )
unlock();
}
QWidget *VstPlugin::pluginWidget(bool _top_widget)
{
if ( m_embedMethod == "none" || !m_pluginWidget )
{
return nullptr;
}
if ( _top_widget && m_pluginWidget->parentWidget() == m_pluginSubWindow )
{
return m_pluginSubWindow;
}
else
{
return m_pluginWidget;
}
}
@@ -439,17 +383,17 @@ bool VstPlugin::processMessage( const message & _m )
{
switch( _m.id )
{
case IdVstBadDllFormat:
m_badDllFormat = true;
break;
case IdVstBadDllFormat:
m_badDllFormat = true;
break;
case IdVstPluginWindowID:
m_pluginWindowID = _m.getInt();
break;
case IdVstPluginWindowID:
m_pluginWindowID = _m.getInt();
break;
case IdVstPluginEditorGeometry:
m_pluginGeometry = QSize( _m.getInt( 0 ),
_m.getInt( 1 ) );
case IdVstPluginEditorGeometry:
m_pluginGeometry = QSize( _m.getInt( 0 ),
_m.getInt( 1 ) );
break;
case IdVstPluginName:
@@ -624,6 +568,46 @@ void VstPlugin::idleUpdate()
unlock();
}
void VstPlugin::showUI()
{
if ( m_embedMethod == "none" )
{
RemotePlugin::showUI();
}
else
{
if (! pluginWidget()) {
createUI( NULL, false );
}
QWidget * w = pluginWidget();
if( w )
{
w->show();
}
}
}
void VstPlugin::hideUI()
{
if ( m_embedMethod == "none" )
{
RemotePlugin::hideUI();
}
else if ( pluginWidget() != nullptr )
{
hideEditor();
}
}
// X11Embed only
void VstPlugin::handleClientEmbed()
{
lock();
sendMessage( IdShowUI );
unlock();
}
void VstPlugin::loadChunk( const QByteArray & _chunk )
@@ -667,6 +651,114 @@ QByteArray VstPlugin::saveChunk()
return a;
}
void VstPlugin::createUI( QWidget * parent, bool isEffect )
{
if( m_pluginWindowID == 0 )
{
return;
}
QWidget* container = nullptr;
m_pluginSubWindow = new vstSubWin( gui->mainWindow()->workspace() );
auto sw = m_pluginSubWindow.data();
#if QT_VERSION >= 0x050100
if (m_embedMethod == "qt" )
{
QWindow* vw = QWindow::fromWinId(m_pluginWindowID);
container = QWidget::createWindowContainer(vw, sw );
container->installEventFilter(this);
} else
#endif
#ifdef LMMS_BUILD_WIN32
if (m_embedMethod == "win32" )
{
QWidget * helper = new QWidget;
QHBoxLayout * l = new QHBoxLayout( helper );
QWidget * target = new QWidget( helper );
l->setSpacing( 0 );
l->setMargin( 0 );
l->addWidget( target );
// we've to call that for making sure, Qt created the windows
helper->winId();
HWND targetHandle = (HWND)target->winId();
HWND pluginHandle = (HWND)(intptr_t)m_pluginWindowID;
DWORD style = GetWindowLong(pluginHandle, GWL_STYLE);
style = style & ~(WS_POPUP);
style = style | WS_CHILD;
SetWindowLong(pluginHandle, GWL_STYLE, style);
SetParent(pluginHandle, targetHandle);
DWORD threadId = GetWindowThreadProcessId(pluginHandle, NULL);
DWORD currentThreadId = GetCurrentThreadId();
AttachThreadInput(currentThreadId, threadId, true);
container = helper;
RemotePlugin::showUI();
} else
#endif
#ifdef LMMS_BUILD_LINUX
if (m_embedMethod == "xembed" )
{
QX11EmbedContainer * embedContainer = new QX11EmbedContainer( sw );
connect(embedContainer, SIGNAL(clientIsEmbedded()), this, SLOT(handleClientEmbed()));
embedContainer->embedClient( m_pluginWindowID );
container = embedContainer;
} else
#endif
{
qCritical() << "Unknown embed method" << m_embedMethod;
delete m_pluginSubWindow;
return;
}
container->setFixedSize( m_pluginGeometry );
container->setWindowTitle( name() );
if( parent == NULL )
{
m_pluginWidget = container;
sw->setWidget(container);
if( isEffect )
{
sw->setAttribute( Qt::WA_TranslucentBackground );
sw->setWindowFlags( Qt::FramelessWindowHint );
}
else
{
sw->setWindowFlags( Qt::WindowCloseButtonHint );
}
};
container->setFixedSize( m_pluginGeometry );
}
bool VstPlugin::eventFilter(QObject *obj, QEvent *event)
{
#if QT_VERSION >= 0x050100
if (embedMethod() == "qt" && obj == m_pluginWidget)
{
if (event->type() == QEvent::Show) {
RemotePlugin::showUI();
}
qDebug() << obj << event;
}
#endif
return false;
}
QString VstPlugin::embedMethod() const
{
return m_embedMethod;
}

View File

@@ -35,6 +35,8 @@
#include "JournallingObject.h"
#include "communication.h"
class vstSubWin;
class PLUGIN_EXPORT VstPlugin : public RemotePlugin, public JournallingObject
{
@@ -52,8 +54,8 @@ public:
return m_pluginWindowID != 0;
}
void showEditor( QWidget * _parent = NULL, bool isEffect = false );
void hideEditor();
void toggleEditor();
inline const QString & name() const
{
@@ -91,17 +93,7 @@ public:
void setParameterDump( const QMap<QString, QString> & _pdump );
inline QWidget * pluginWidget( bool _top_widget = true )
{
if( _top_widget && m_pluginWidget )
{
if( m_pluginWidget->parentWidget() )
{
return m_pluginWidget->parentWidget();
}
}
return m_pluginWidget;
}
QWidget * pluginWidget( bool _top_widget = true );
virtual void loadSettings( const QDomElement & _this );
virtual void saveSettings( QDomDocument & _doc, QDomElement & _this );
@@ -111,6 +103,12 @@ public:
return "vstplugin";
}
void toggleUI() override;
void createUI( QWidget *parent, bool isEffect );
bool eventFilter(QObject *obj, QEvent *event);
QString embedMethod() const;
public slots:
void setTempo( bpm_t _bpm );
@@ -123,6 +121,10 @@ public slots:
void setParam( int i, float f );
void idleUpdate();
void showUI() override;
void hideUI() override;
void handleClientEmbed();
private:
void loadChunk( const QByteArray & _chunk );
@@ -130,8 +132,10 @@ private:
QString m_plugin;
QPointer<QWidget> m_pluginWidget;
QPointer<vstSubWin> m_pluginSubWindow;
int m_pluginWindowID;
QSize m_pluginGeometry;
const QString m_embedMethod;
bool m_badDllFormat;

View File

@@ -1,166 +0,0 @@
/* basename.c
*
* $Id: basename.c,v 1.2 2007/03/08 23:15:58 keithmarshall Exp $
*
* Provides an implementation of the "basename" function, conforming
* to SUSv3, with extensions to accommodate Win32 drive designators,
* and suitable for use on native Microsoft(R) Win32 platforms.
*
* Written by Keith Marshall <keithmarshall@users.sourceforge.net>
*
* This is free software. You may redistribute and/or modify it as you
* see fit, without restriction of copyright.
*
* This software is provided "as is", in the hope that it may be useful,
* but WITHOUT WARRANTY OF ANY KIND, not even any implied warranty of
* MERCHANTABILITY, nor of FITNESS FOR ANY PARTICULAR PURPOSE. At no
* time will the author accept any form of liability for any damages,
* however caused, resulting from the use of this software.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
#ifndef __cdecl /* If compiling on any non-Win32 platform ... */
#define __cdecl /* this may not be defined. */
#endif
__cdecl char *basename( char *path )
{
size_t len;
static char *retfail = NULL;
/* to handle path names for files in multibyte character locales,
* we need to set up LC_CTYPE to match the host file system locale
*/
char *locale = setlocale( LC_CTYPE, NULL );
if( locale != NULL ) locale = strdup( locale );
setlocale( LC_CTYPE, "" );
if( path && *path )
{
/* allocate sufficient local storage space,
* in which to create a wide character reference copy of path
*/
wchar_t refcopy[1 + (len = mbstowcs( NULL, path, 0 ))];
/* create the wide character reference copy of path,
* and step over the drive designator, if present ...
*/
wchar_t *refpath = refcopy;
if( ((len = mbstowcs( refpath, path, len )) > 1) && (refpath[1] == L':') )
{
/* FIXME: maybe should confirm *refpath is a valid drive designator */
refpath += 2;
}
/* ensure that our wide character reference path is NUL terminated */
refcopy[ len ] = L'\0';
/* check again, just to ensure we still have a non-empty path name ... */
if( *refpath )
{
/* and, when we do, process it in the wide character domain ...
* scanning from left to right, to the char after the final dir separator
*/
wchar_t *refname;
for( refname = refpath ; *refpath ; ++refpath )
{
if( (*refpath == L'/') || (*refpath == L'\\') )
{
/* we found a dir separator ...
* step over it, and any others which immediately follow it
*/
while( (*refpath == L'/') || (*refpath == L'\\') )
++refpath;
/* if we didn't reach the end of the path string ... */
if( *refpath )
/* then we have a new candidate for the base name */
refname = refpath;
/* otherwise ...
* strip off any trailing dir separators which we found
*/
else while( (refpath > refname)
&& ((*--refpath == L'/') || (*refpath == L'\\')) )
*refpath = L'\0';
}
}
/* in the wide character domain ...
* refname now points at the resolved base name ...
*/
if( *refname )
{
/* if it's not empty,
* then we transform the full normalised path back into
* the multibyte character domain, and skip over the dirname,
* to return the resolved basename.
*/
if( (len = wcstombs( path, refcopy, len )) != (size_t)(-1) )
path[ len ] = '\0';
*refname = L'\0';
if( (len = wcstombs( NULL, refcopy, 0 )) != (size_t)(-1) )
path += len;
}
else
{
/* the basename is empty, so return the default value of "/",
* transforming from wide char to multibyte char domain, and
* returning it in our own buffer.
*/
retfail = (char *) realloc( retfail, len = 1 + wcstombs( NULL, L"/", 0 ));
wcstombs( path = retfail, L"/", len );
}
/* restore the caller's locale, clean up, and return the result */
setlocale( LC_CTYPE, locale );
free( locale );
return( path );
}
/* or we had an empty residual path name, after the drive designator,
* in which case we simply fall through ...
*/
}
/* and, if we get to here ...
* the path name is either NULL, or it decomposes to an empty string;
* in either case, we return the default value of "." in our own buffer,
* reloading it with the correct value, transformed from the wide char
* to the multibyte char domain, just in case the caller trashed it
* after a previous call.
*/
retfail = (char *) realloc( retfail, len = 1 + wcstombs( NULL, L".", 0 ));
wcstombs( retfail, L".", len );
/* restore the caller's locale, clean up, and return the result */
setlocale( LC_CTYPE, locale );
free( locale );
return( retfail );
}
/* $RCSfile: basename.c,v $$Revision: 1.2 $: end of file */

View File

@@ -30,6 +30,7 @@
#include "RemotePlugin.h"
struct VstParameterDumpItem
{
int32_t index;
@@ -56,7 +57,6 @@ enum VstRemoteMessageIDs
{
// vstPlugin -> remoteVstPlugin
IdVstLoadPlugin = IdUserBase,
IdVstPluginWindowInformation,
IdVstClosePlugin,
IdVstSetTempo,
IdVstSetLanguage,

View File

@@ -445,8 +445,8 @@ void ZynAddSubFxInstrument::initPlugin()
RemotePlugin::message( IdZasfPresetDirectory ).
addString(
QSTR_TO_STDSTR(
QString( ConfigManager::inst()->factoryPresetsDir() +
QDir::separator() + "ZynAddSubFX" ) ) ) );
QDir( ConfigManager::inst()->factoryPresetsDir() +
"/ZynAddSubFX" ).absolutePath() ) ) );
m_remotePlugin->updateSampleRate( Engine::mixer()->processingSampleRate() );

9
src/3rdparty/CMakeLists.txt vendored Normal file
View File

@@ -0,0 +1,9 @@
set(CMAKE_C_FLAGS "")
set(CMAKE_CXX_FLAGS "")
IF(QT5 AND LMMS_BUILD_LINUX)
set(BUILD_SHARED_LIBS OFF)
add_subdirectory(qt5-x11embed)
ENDIF()
ADD_SUBDIRECTORY(rpmalloc)

1
src/3rdparty/qt5-x11embed vendored Submodule

37
src/3rdparty/rpmalloc/CMakeLists.txt vendored Normal file
View File

@@ -0,0 +1,37 @@
set(CMAKE_C_FLAGS "-std=c11")
add_library(rpmalloc STATIC
rpmalloc/rpmalloc/rpmalloc.c
rpmalloc/rpmalloc/rpmalloc.h
)
target_include_directories(rpmalloc PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/rpmalloc/rpmalloc
)
if (NOT LMMS_BUILD_WIN32)
target_compile_definitions(rpmalloc
PRIVATE -D_GNU_SOURCE
)
endif()
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
# rpmalloc uses GCC builtin "__builtin_umull_overflow" with ENABLE_VALIDATE_ARGS,
# which is only available starting with GCC 5
if (CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_LESS 5)
set(ENABLE_VALIDATE_ARGS OFF)
else ()
set(ENABLE_VALIDATE_ARGS ON)
endif()
target_compile_definitions(rpmalloc
PRIVATE -DENABLE_ASSERTS=1 -DENABLE_VALIDATE_ARGS=${ENABLE_VALIDATE_ARGS}
)
endif()
option(LMMS_ENABLE_MALLOC_STATS "Enables statistics for rpmalloc" OFF)
if (LMMS_ENABLE_MALLOC_STATS)
target_compile_definitions(rpmalloc
PRIVATE -DENABLE_STATISTICS=1
)
endif()

View File

@@ -1,3 +1,5 @@
ADD_SUBDIRECTORY(3rdparty)
CONFIGURE_FILE("lmmsconfig.h.in" "${CMAKE_BINARY_DIR}/lmmsconfig.h")
CONFIGURE_FILE("lmmsversion.h.in" "${CMAKE_BINARY_DIR}/lmmsversion.h")
@@ -8,7 +10,7 @@ SET(CMAKE_AUTOMOC ON)
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
# Enable C++11
ADD_DEFINITIONS(-std=c++0x)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
IF(LMMS_BUILD_APPLE)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
@@ -132,7 +134,7 @@ IF(LMMS_BUILD_HAIKU)
SET(EXTRA_LIBRARIES "-lnetwork")
ENDIF()
SET(LMMS_REQUIRED_LIBS
SET(LMMS_REQUIRED_LIBS ${LMMS_REQUIRED_LIBS}
${CMAKE_THREAD_LIBS_INIT}
${QT_LIBRARIES}
${ASOUND_LIBRARY}
@@ -147,7 +149,9 @@ SET(LMMS_REQUIRED_LIBS
${SAMPLERATE_LIBRARIES}
${SNDFILE_LIBRARIES}
${EXTRA_LIBRARIES}
rpmalloc
)
# Expose required libs for tests binary
SET(LMMS_REQUIRED_LIBS ${LMMS_REQUIRED_LIBS} PARENT_SCOPE)
@@ -155,6 +159,16 @@ TARGET_LINK_LIBRARIES(lmms
${LMMS_REQUIRED_LIBS}
)
FOREACH(LIB ${LMMS_REQUIRED_LIBS})
IF(TARGET ${LIB})
GET_TARGET_PROPERTY(INCLUDE_DIRS ${LIB} INTERFACE_INCLUDE_DIRECTORIES)
if (INCLUDE_DIRS)
TARGET_INCLUDE_DIRECTORIES(lmmsobjs PRIVATE ${INCLUDE_DIRS})
ENDIF()
ENDIF()
ENDFOREACH()
# Required libs for debug msys builds
IF(LMMS_BUILD_MSYS AND CMAKE_BUILD_TYPE STREQUAL "Debug")
TARGET_LINK_LIBRARIES(lmms QtCore4 QtGui4 QtXml4)

View File

@@ -42,8 +42,6 @@ AutomatableModel::AutomatableModel( DataType type,
Model( parent, displayName, defaultConstructed ),
m_dataType( type ),
m_scaleType( Linear ),
m_value( val ),
m_initValue( val ),
m_minValue( min ),
m_maxValue( max ),
m_step( step ),
@@ -59,6 +57,7 @@ AutomatableModel::AutomatableModel( DataType type,
m_hasSampleExactData( false )
{
m_value = fittedValue( val );
setInitValue( val );
}
@@ -523,14 +522,8 @@ float AutomatableModel::controllerValue( int frameOffset ) const
ValueBuffer * AutomatableModel::valueBuffer()
{
// if we've already calculated the valuebuffer this period, return the cached buffer
if( m_lastUpdatedPeriod == s_periodCounter )
{
return m_hasSampleExactData
? &m_valueBuffer
: NULL;
}
QMutexLocker m( &m_valueBufferMutex );
// if we've already calculated the valuebuffer this period, return the cached buffer
if( m_lastUpdatedPeriod == s_periodCounter )
{
return m_hasSampleExactData
@@ -626,6 +619,7 @@ void AutomatableModel::setInitValue( const float value )
m_initValue = fittedValue( value );
bool journalling = testAndSetJournalling( false );
setValue( value );
m_oldValue = m_value;
setJournalling( journalling );
emit initValueChanged( value );
}

View File

@@ -1,3 +1,16 @@
IF(LMMS_HAVE_WEAKJACK)
set(WEAKJACK core/audio/AudioWeakJack.c)
# Build libjack.so.0 stub as weakjack.so for AppImages
IF(LMMS_BUILD_LINUX)
ADD_LIBRARY(weakjack MODULE ../../src/core/audio/AudioWeakJack.c)
INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/include")
# We can't predict an AppImage build, so stash the build artifact for later
INSTALL(TARGETS weakjack LIBRARY DESTINATION "${CMAKE_BINARY_DIR}/optional")
SET_TARGET_PROPERTIES(weakjack PROPERTIES PREFIX "" SUFFIX ".so")
ENDIF()
ENDIF()
set(LMMS_SRCS
${LMMS_SRCS}
core/AutomatableModel.cpp
@@ -72,6 +85,7 @@ set(LMMS_SRCS
core/audio/AudioFileMP3.cpp
core/audio/AudioFileOgg.cpp
core/audio/AudioFileWave.cpp
${WEAKJACK}
core/audio/AudioJack.cpp
core/audio/AudioOss.cpp
core/audio/AudioSndio.cpp

View File

@@ -186,6 +186,39 @@ QString ConfigManager::defaultVersion() const
return LMMS_VERSION;
}
QStringList ConfigManager::availabeVstEmbedMethods()
{
QStringList methods;
methods.append("none");
#if QT_VERSION >= 0x050100
methods.append("qt");
#endif
#ifdef LMMS_BUILD_WIN32
methods.append("win32");
#endif
#ifdef LMMS_BUILD_LINUX
#if QT_VERSION >= 0x050000
if (static_cast<QGuiApplication*>(QApplication::instance())->
platformName() == "xcb")
#else
if (qgetenv("QT_QPA_PLATFORM").isNull()
|| qgetenv("QT_QPA_PLATFORM") == "xcb")
#endif
{
methods.append("xembed");
}
#endif
return methods;
}
QString ConfigManager::vstEmbedMethod() const
{
QStringList methods = availabeVstEmbedMethods();
QString defaultMethod = *(methods.end() - 1);
QString currentMethod = value( "ui", "vstembedmethod", defaultMethod );
return methods.contains(currentMethod) ? currentMethod : defaultMethod;
}
bool ConfigManager::hasWorkingDir() const
{
return QDir( m_workingDir ).exists();
@@ -336,12 +369,15 @@ void ConfigManager::setValue( const QString & cls,
{
if( m_settings.contains( cls ) )
{
for( stringPairVector::iterator it = m_settings[cls].begin();
it != m_settings[cls].end(); ++it )
for( QPair<QString, QString>& pair : m_settings[cls])
{
if( ( *it ).first == attribute )
if( pair.first == attribute )
{
( *it ).second = value;
if ( pair.second != value )
{
pair.second = value;
emit valueChanged( cls, attribute, value );
}
return;
}
}
@@ -503,7 +539,16 @@ void ConfigManager::loadConfigFile( const QString & configFile )
#elif defined(LMMS_BUILD_APPLE)
m_stkDir = qApp->applicationDirPath() + "/../share/stk/rawwaves/";
#else
m_stkDir = "/usr/share/stk/rawwaves/";
if ( qApp->applicationDirPath().startsWith("/tmp/") )
{
// Assume AppImage bundle
m_stkDir = qApp->applicationDirPath() + "/../share/stk/rawwaves/";
}
else
{
// Fallback to system provided location
m_stkDir = "/usr/share/stk/rawwaves/";
}
#endif
}
#endif

View File

@@ -305,7 +305,7 @@ InstrumentFunctionArpeggio::InstrumentFunctionArpeggio( Model * _parent ) :
m_arpCycleModel( 0.0f, 0.0f, 6.0f, 1.0f, this, tr( "Cycle steps" ) ),
m_arpSkipModel( 0.0f, 0.0f, 100.0f, 1.0f, this, tr( "Skip rate" ) ),
m_arpMissModel( 0.0f, 0.0f, 100.0f, 1.0f, this, tr( "Miss rate" ) ),
m_arpTimeModel( 100.0f, 25.0f, 2000.0f, 1.0f, 2000, this, tr( "Arpeggio time" ) ),
m_arpTimeModel( 200.0f, 25.0f, 2000.0f, 1.0f, 2000, this, tr( "Arpeggio time" ) ),
m_arpGateModel( 100.0f, 1.0f, 200.0f, 1.0f, this, tr( "Arpeggio gate" ) ),
m_arpDirectionModel( this, tr( "Arpeggio direction" ) ),
m_arpModeModel( this, tr( "Arpeggio mode" ) )
@@ -396,14 +396,13 @@ void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n )
frames_processed += remaining_frames_for_cur_arp;
// init with zero
int cur_arp_idx = 0;
// in sorted mode: is it our turn or do we have to be quiet for
// now?
if( m_arpModeModel.value() == SortMode &&
( ( cur_frame / arp_frames ) % total_range ) / range != (f_cnt_t) _n->index() )
{
// Set master note if not playing arp note or it will play as an ordinary note
_n->setMasterNote();
// update counters
frames_processed += arp_frames;
cur_frame += arp_frames;
@@ -416,10 +415,9 @@ void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n )
if( 100 * ( (float) rand() / (float)( RAND_MAX + 1.0f ) ) < m_arpSkipModel.value() )
{
if( cur_arp_idx == 0 )
{
_n->setMasterNote();
}
// Set master note to prevent the note to extend over skipped notes
// This may only be needed for lb302
_n->setMasterNote();
// update counters
frames_processed += arp_frames;
cur_frame += arp_frames;
@@ -440,6 +438,7 @@ void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n )
}
}
int cur_arp_idx = 0;
// process according to arpeggio-direction...
if( dir == ArpDirUp )
{
@@ -525,6 +524,13 @@ void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n )
frames_processed += arp_frames;
cur_frame += arp_frames;
}
// make sure note is handled as arp-base-note, even
// if we didn't add a sub-note so far
if( m_arpModeModel.value() != FreeMode )
{
_n->setMasterNote();
}
}

View File

@@ -299,13 +299,22 @@ f_cnt_t InstrumentSoundShaping::envFrames( const bool _only_vol ) const
f_cnt_t InstrumentSoundShaping::releaseFrames() const
{
if( !m_instrumentTrack->instrument() )
{
return 0;
}
f_cnt_t ret_val = m_instrumentTrack->instrument()->desiredReleaseFrames();
if( m_instrumentTrack->instrument()->flags().testFlag( Instrument::IsSingleStreamed ) )
{
return ret_val;
}
if( m_envLfoParameters[Volume]->isUsed() )
{
return m_envLfoParameters[Volume]->releaseFrames();
}
f_cnt_t ret_val = m_instrumentTrack->instrument()
? m_instrumentTrack->instrument()->desiredReleaseFrames()
: 0;
for( int i = Volume+1; i < NumTargets; ++i )
{

View File

@@ -1,8 +1,7 @@
/*
* MemoryManager.cpp - A lightweight, generic memory manager for LMMS
* MemoryManager.cpp
*
* Copyright (c) 2014 Vesa Kivimäki
* Copyright (c) 2007-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2017 Lukas W <lukaswhl/at/gmail.com>
*
* This file is part of LMMS - https://lmms.io
*
@@ -25,197 +24,54 @@
#include "MemoryManager.h"
#include <QReadWriteLock>
#include <QtCore/QtGlobal>
#include "rpmalloc.h"
/// Global static object handling rpmalloc intializing and finalizing
struct MemoryManagerGlobalGuard {
MemoryManagerGlobalGuard() {
rpmalloc_initialize();
}
~MemoryManagerGlobalGuard() {
rpmalloc_finalize();
}
} static mm_global_guard;
MemoryPoolVector MemoryManager::s_memoryPools;
QReadWriteLock MemoryManager::s_poolMutex;
PointerInfoMap MemoryManager::s_pointerInfo;
QMutex MemoryManager::s_pointerMutex;
bool MemoryManager::init()
{
s_memoryPools.reserve( 64 );
s_pointerInfo.reserve( 4096 );
// construct first MemoryPool and allocate memory
MemoryPool m ( MM_INITIAL_CHUNKS );
m.m_pool = MemoryHelper::alignedMalloc( MM_INITIAL_CHUNKS * MM_CHUNK_SIZE );
s_memoryPools.append( m );
return true;
namespace {
static thread_local size_t thread_guard_depth;
}
void * MemoryManager::alloc( size_t size )
MemoryManager::ThreadGuard::ThreadGuard()
{
if( !size )
{
return NULL;
}
int requiredChunks = size / MM_CHUNK_SIZE + ( size % MM_CHUNK_SIZE > 0 ? 1 : 0 );
MemoryPool * mp = NULL;
void * ptr = NULL;
MemoryPoolVector::iterator it = s_memoryPools.begin();
s_poolMutex.lockForRead();
while( it != s_memoryPools.end() && !ptr )
{
ptr = ( *it ).getChunks( requiredChunks );
if( ptr )
{
mp = &( *it );
}
++it;
}
s_poolMutex.unlock();
if( ptr )
{
s_pointerMutex.lock();
PtrInfo p;
p.chunks = requiredChunks;
p.memPool = mp;
s_pointerInfo[ptr] = p;
s_pointerMutex.unlock();
return ptr;
}
// can't find enough chunks in existing pools, so
// create a new pool that is guaranteed to have enough chunks
int moreChunks = qMax( requiredChunks, MM_INCREMENT_CHUNKS );
int i = MemoryManager::extend( moreChunks );
mp = &s_memoryPools[i];
ptr = s_memoryPools[i].getChunks( requiredChunks );
if( ptr )
{
s_pointerMutex.lock();
PtrInfo p;
p.chunks = requiredChunks;
p.memPool = mp;
s_pointerInfo[ptr] = p;
s_pointerMutex.unlock();
return ptr;
}
// still no luck? something is horribly wrong
qFatal( "MemoryManager.cpp: Couldn't allocate memory: %d chunks asked", requiredChunks );
return NULL;
}
void MemoryManager::free( void * ptr )
{
if( !ptr )
{
return; // Null pointer deallocations are OK but do not need to be handled
}
// fetch info on the ptr and remove
s_pointerMutex.lock();
if( ! s_pointerInfo.contains( ptr ) ) // if we have no info on ptr, fail loudly
{
qFatal( "MemoryManager: Couldn't find pointer info for pointer: %p", ptr );
}
PtrInfo p = s_pointerInfo[ptr];
s_pointerInfo.remove( ptr );
s_pointerMutex.unlock();
p.memPool->releaseChunks( ptr, p.chunks );
}
int MemoryManager::extend( int chunks )
{
MemoryPool m ( chunks );
m.m_pool = MemoryHelper::alignedMalloc( chunks * MM_CHUNK_SIZE );
s_poolMutex.lockForWrite();
s_memoryPools.append( m );
int i = s_memoryPools.size() - 1;
s_poolMutex.unlock();
return i;
}
void MemoryManager::cleanup()
{
for( MemoryPoolVector::iterator it = s_memoryPools.begin(); it != s_memoryPools.end(); ++it )
{
MemoryHelper::alignedFree( ( *it ).m_pool );
MemoryHelper::alignedFree( ( *it ).m_free );
if (thread_guard_depth++ == 0) {
rpmalloc_thread_initialize();
}
}
void * MemoryPool::getChunks( int chunksNeeded )
MemoryManager::ThreadGuard::~ThreadGuard()
{
if( chunksNeeded > m_chunks ) // not enough chunks in this pool?
{
return NULL;
if (--thread_guard_depth == 0) {
rpmalloc_thread_finalize();
}
}
m_mutex.lock();
static thread_local MemoryManager::ThreadGuard local_mm_thread_guard{};
// now find out if we have a long enough sequence of chunks in this pool
char last = 0;
intptr_t n = 0;
intptr_t index = -1;
bool found = false;
for( int i = 0; i < m_chunks; ++i )
{
if( m_free[i] )
{
if( !last )
{
index = i;
}
++n;
if( n >= chunksNeeded )
{
found = true;
break;
}
}
else
{
n = 0;
}
last = m_free[i];
}
if( found ) // if enough chunks found, return pointer to chunks
{
// set chunk flags to false so we know the chunks are in use
for( intptr_t i = 0; i < chunksNeeded; ++i )
{
m_free[ index + i ] = 0;
}
m_mutex.unlock();
return (char*)m_pool + ( index * MM_CHUNK_SIZE );
}
m_mutex.unlock();
return NULL; // out of stock, come again tomorrow!
void* MemoryManager::alloc(size_t size)
{
// Reference local thread guard to ensure it is initialized.
// Compilers may optimize the instance away otherwise.
Q_UNUSED(&local_mm_thread_guard);
Q_ASSERT_X(rpmalloc_is_thread_initialized(), "MemoryManager::alloc", "Thread not initialized");
return rpmalloc(size);
}
void MemoryPool::releaseChunks( void * ptr, int chunks )
void MemoryManager::free(void * ptr)
{
m_mutex.lock();
intptr_t start = ( (intptr_t)ptr - (intptr_t)m_pool ) / MM_CHUNK_SIZE;
if( start < 0 )
{
qFatal( "MemoryManager: error at releaseChunks() - corrupt pointer info?" );
}
memset( &m_free[ start ], 1, chunks );
m_mutex.unlock();
Q_UNUSED(&local_mm_thread_guard);
Q_ASSERT_X(rpmalloc_is_thread_initialized(), "MemoryManager::free", "Thread not initialized");
return rpfree(ptr);
}

View File

@@ -36,6 +36,7 @@
#include "NotePlayHandle.h"
#include "ConfigManager.h"
#include "SamplePlayHandle.h"
#include "MemoryHelper.h"
// platform-specific audio-interface-classes
#include "AudioAlsa.h"
@@ -500,6 +501,20 @@ void Mixer::clear()
void Mixer::clearNewPlayHandles()
{
requestChangeInModel();
for( LocklessListElement * e = m_newPlayHandles.popList(); e; )
{
LocklessListElement * next = e->next;
m_newPlayHandles.free( e );
e = next;
}
doneChangeInModel();
}
// removes all play-handles. this is necessary, when the song is stopped ->
// all remaining notes etc. would be played until their end
void Mixer::clearInternal()

View File

@@ -153,6 +153,7 @@ void MixerWorkerThread::startAndWaitForJobs()
void MixerWorkerThread::run()
{
MemoryManager::ThreadGuard mmThreadGuard; Q_UNUSED(mmThreadGuard);
disable_denormals();
QMutex m;

View File

@@ -128,7 +128,7 @@ NotePlayHandle::NotePlayHandle( InstrumentTrack* instrumentTrack,
}
void NotePlayHandle::done()
NotePlayHandle::~NotePlayHandle()
{
lock();
noteOff( 0 );
@@ -599,7 +599,7 @@ NotePlayHandle * NotePlayHandleManager::acquire( InstrumentTrack* instrumentTrac
void NotePlayHandleManager::release( NotePlayHandle * nph )
{
nph->done();
nph->NotePlayHandle::~NotePlayHandle();
s_mutex.lockForRead();
s_available[ s_availableIndex.fetchAndAddOrdered( 1 ) + 1 ] = nph;
s_mutex.unlock();

View File

@@ -54,6 +54,7 @@ void PlayHandle::doProcessing()
if( m_usesBuffer )
{
m_bufferReleased = false;
BufferManager::clear(m_playHandleBuffer, Engine::mixer()->framesPerPeriod());
play( buffer() );
}
else

View File

@@ -22,6 +22,7 @@
*
*/
#include <QAtomicPointer>
#include <QFileInfo>
#include "PresetPreviewPlayHandle.h"
@@ -66,12 +67,25 @@ public:
NotePlayHandle* previewNote()
{
#if QT_VERSION >= 0x050000
return m_previewNote.loadAcquire();
#else
return m_previewNote;
#endif
}
void setPreviewNote( NotePlayHandle * _note )
{
#if QT_VERSION >= 0x050000
m_previewNote.storeRelease( _note );
#else
m_previewNote = _note;
#endif
}
bool testAndSetPreviewNote( NotePlayHandle * expectedVal, NotePlayHandle * newVal )
{
return m_previewNote.testAndSetOrdered( expectedVal, newVal );
}
void lockData()
@@ -97,7 +111,7 @@ public:
private:
InstrumentTrack* m_previewInstrumentTrack;
NotePlayHandle* m_previewNote;
QAtomicPointer<NotePlayHandle> m_previewNote;
QMutex m_dataMutex;
friend class PresetPreviewPlayHandle;
@@ -113,15 +127,14 @@ PresetPreviewPlayHandle::PresetPreviewPlayHandle( const QString & _preset_file,
PlayHandle( TypePresetPreviewHandle ),
m_previewNote( NULL )
{
s_previewTC->lockData();
setUsesBuffer( false );
if( s_previewTC->previewNote() != NULL )
{
s_previewTC->previewNote()->mute();
}
s_previewTC->lockData();
Engine::mixer()->requestChangeInModel();
s_previewTC->setPreviewNote( nullptr );
s_previewTC->previewInstrumentTrack()->silenceAllNotes();
Engine::mixer()->doneChangeInModel();
const bool j = Engine::projectJournal()->isJournalling();
Engine::projectJournal()->setJournalling( false );
@@ -174,6 +187,7 @@ PresetPreviewPlayHandle::PresetPreviewPlayHandle( const QString & _preset_file,
s_previewTC->previewInstrumentTrack()->
midiPort()->setMode( MidiPort::Disabled );
Engine::mixer()->requestChangeInModel();
// create note-play-handle for it
m_previewNote = NotePlayHandleManager::acquire(
s_previewTC->previewInstrumentTrack(), 0,
@@ -186,6 +200,7 @@ PresetPreviewPlayHandle::PresetPreviewPlayHandle( const QString & _preset_file,
Engine::mixer()->addPlayHandle( m_previewNote );
Engine::mixer()->doneChangeInModel();
s_previewTC->unlockData();
Engine::projectJournal()->setJournalling( j );
}
@@ -195,15 +210,13 @@ PresetPreviewPlayHandle::PresetPreviewPlayHandle( const QString & _preset_file,
PresetPreviewPlayHandle::~PresetPreviewPlayHandle()
{
s_previewTC->lockData();
Engine::mixer()->requestChangeInModel();
// not muted by other preset-preview-handle?
if( !m_previewNote->isMuted() )
if (s_previewTC->testAndSetPreviewNote(m_previewNote, nullptr))
{
// then set according state
s_previewTC->setPreviewNote( NULL );
m_previewNote->noteOff();
}
m_previewNote->noteOff();
s_previewTC->unlockData();
Engine::mixer()->doneChangeInModel();
}
@@ -228,7 +241,7 @@ bool PresetPreviewPlayHandle::isFinished() const
bool PresetPreviewPlayHandle::isFromTrack( const Track * _track ) const
{
return s_previewTC->previewInstrumentTrack() == _track;
return s_previewTC && s_previewTC->previewInstrumentTrack() == _track;
}
@@ -258,13 +271,11 @@ ConstNotePlayHandleList PresetPreviewPlayHandle::nphsOfInstrumentTrack(
const InstrumentTrack * _it )
{
ConstNotePlayHandleList cnphv;
s_previewTC->lockData();
if( s_previewTC->previewNote() != NULL &&
s_previewTC->previewNote()->instrumentTrack() == _it )
{
cnphv.push_back( s_previewTC->previewNote() );
}
s_previewTC->unlockData();
return cnphv;
}

View File

@@ -163,6 +163,7 @@ void ProjectRenderer::startProcessing()
void ProjectRenderer::run()
{
MemoryManager::ThreadGuard mmThreadGuard; Q_UNUSED(mmThreadGuard);
#if 0
#ifdef LMMS_BUILD_LINUX
#ifdef LMMS_HAVE_SCHED_H

View File

@@ -164,8 +164,8 @@ RemotePlugin::~RemotePlugin()
bool RemotePlugin::init( const QString &pluginExecutable,
bool waitForInitDoneMsg )
bool RemotePlugin::init(const QString &pluginExecutable,
bool waitForInitDoneMsg , QStringList extraArgs)
{
lock();
if( m_failed )
@@ -208,6 +208,7 @@ bool RemotePlugin::init( const QString &pluginExecutable,
#else
args << m_socketFile;
#endif
args << extraArgs;
#ifndef DEBUG_REMOTE_PLUGIN
m_process.setProcessChannelMode( QProcess::ForwardedChannels );
m_process.setWorkingDirectory( QCoreApplication::applicationDirPath() );
@@ -392,6 +393,20 @@ void RemotePlugin::processMidiEvent( const MidiEvent & _e,
unlock();
}
void RemotePlugin::showUI()
{
lock();
sendMessage( IdShowUI );
unlock();
}
void RemotePlugin::hideUI()
{
lock();
sendMessage( IdHideUI );
unlock();
}

View File

@@ -86,6 +86,7 @@ Song::Song() :
m_playing( false ),
m_paused( false ),
m_loadingProject( false ),
m_isCancelled( false ),
m_playMode( Mode_None ),
m_length( 0 ),
m_patternToPlay( NULL ),
@@ -1074,7 +1075,7 @@ void Song::loadProject( const QString & fileName )
}
}
while( !node.isNull() )
while( !node.isNull() && !isCancelled() )
{
if( node.isElement() )
{
@@ -1133,6 +1134,13 @@ void Song::loadProject( const QString & fileName )
emit projectLoaded();
if( isCancelled() )
{
m_isCancelled = false;
createNewProject();
return;
}
if ( hasErrors())
{
if ( gui )
@@ -1278,7 +1286,7 @@ void Song::saveControllerStates( QDomDocument & doc, QDomElement & element )
void Song::restoreControllerStates( const QDomElement & element )
{
QDomNode node = element.firstChild();
while( !node.isNull() )
while( !node.isNull() && !isCancelled() )
{
Controller * c = Controller::create( node.toElement(), this );
Q_ASSERT( c != NULL );

View File

@@ -33,12 +33,14 @@
#include "AutomationTrack.h"
#include "BBTrack.h"
#include "BBTrackContainer.h"
#include "embed.h"
#include "TrackContainer.h"
#include "InstrumentTrack.h"
#include "Song.h"
#include "GuiApplication.h"
#include "MainWindow.h"
#include "TextFloat.h"
TrackContainer::TrackContainer() :
Model( NULL ),
@@ -110,6 +112,14 @@ void TrackContainer::loadSettings( const QDomElement & _this )
QEventLoop::AllEvents, 100 );
if( pd->wasCanceled() )
{
if ( gui )
{
TextFloat::displayMessage( tr( "Loading cancelled" ),
tr( "Project loading was cancelled." ),
embed::getIconPixmap( "project_file", 24, 24 ),
2000 );
}
Engine::getSong()->loadingCancelled();
break;
}
}
@@ -286,6 +296,9 @@ AutomatedValueMap TrackContainer::automatedValuesFromTracks(const TrackList &tra
continue;
}
MidiTime relTime = time - p->startPosition();
if (! p->getAutoResize()) {
relTime = qMin(relTime, p->length());
}
float value = p->valueAt(relTime);
for (AutomatableModel* model : p->objects())

View File

@@ -71,6 +71,7 @@ AudioJack::AudioJack( bool & _success_ful, Mixer* _mixer ) :
AudioJack::~AudioJack()
{
stopProcessing();
#ifdef AUDIO_PORT_SUPPORT
while( m_portMap.size() )
{
@@ -200,6 +201,7 @@ bool AudioJack::initJackClient()
void AudioJack::startProcessing()
{
QMutexLocker m( &m_processingMutex );
m_stopped = false;
if( m_active || m_client == NULL )
@@ -252,6 +254,8 @@ void AudioJack::startProcessing()
void AudioJack::stopProcessing()
{
QMutexLocker m( &m_processingMutex );
m_stopped = true;
}
@@ -338,6 +342,8 @@ void AudioJack::renamePort( AudioPort * _port )
int AudioJack::processCallback( jack_nframes_t _nframes, void * _udata )
{
QMutexLocker m( &m_processingMutex );
// do midi processing first so that midi input can
// add to the following sound processing
if( m_midiClient && _nframes > 0 )
@@ -397,15 +403,15 @@ int AudioJack::processCallback( jack_nframes_t _nframes, void * _udata )
if( m_framesDoneInCurBuf == m_framesToDoInCurBuf )
{
m_framesToDoInCurBuf = getNextBuffer( m_outBuf );
m_framesDoneInCurBuf = 0;
if( !m_framesToDoInCurBuf )
{
m_stopped = true;
break;
}
m_framesDoneInCurBuf = 0;
}
}
if( m_stopped == true )
if( _nframes != done )
{
for( int c = 0; c < channels(); ++c )
{

View File

@@ -27,9 +27,9 @@
#ifdef LMMS_HAVE_SNDIO
#include <QtCore/QFileInfo>
#include <QtGui/QLabel>
#include <QtGui/QLineEdit>
#include <QFileInfo>
#include <QLabel>
#include <QLineEdit>
#include "endian_handling.h"
#include "LcdSpinBox.h"
@@ -52,9 +52,10 @@
AudioSndio::AudioSndio(bool & _success_ful, Mixer * _mixer) :
AudioDevice( tLimit<ch_cnt_t>(
ConfigManager::inst()->value( "audiosndio", "channels" ).toInt(),
DEFAULT_CHANNELS, SURROUND_CHANNELS ), _mixer )
DEFAULT_CHANNELS, SURROUND_CHANNELS ), _mixer ),
m_convertEndian ( false )
{
_success_ful = FALSE;
_success_ful = false;
QString dev = ConfigManager::inst()->value( "audiosndio", "device" );
@@ -64,7 +65,7 @@ AudioSndio::AudioSndio(bool & _success_ful, Mixer * _mixer) :
}
else
{
m_hdl = sio_open( dev.toAscii().data(), SIO_PLAY, 0 );
m_hdl = sio_open( dev.toLatin1().constData(), SIO_PLAY, 0 );
}
if( m_hdl == NULL )
@@ -82,6 +83,11 @@ AudioSndio::AudioSndio(bool & _success_ful, Mixer * _mixer) :
m_par.round = mixer()->framesPerPeriod();
m_par.appbufsz = m_par.round * 2;
if ( (isLittleEndian() && (m_par.le == 0)) ||
(!isLittleEndian() && (m_par.le == 1))) {
m_convertEndian = true;
}
struct sio_par reqpar = m_par;
if (!sio_setpar(m_hdl, &m_par))
@@ -98,7 +104,7 @@ AudioSndio::AudioSndio(bool & _success_ful, Mixer * _mixer) :
if (reqpar.pchan != m_par.pchan ||
reqpar.bits != m_par.bits ||
reqpar.le != m_par.le ||
(abs(reqpar.rate - m_par.rate) * 100)/reqpar.rate > 2)
(::abs(static_cast<int>(reqpar.rate) - static_cast<int>(m_par.rate)) * 100)/reqpar.rate > 2)
{
printf( "sndio: returned params not as requested\n" );
return;
@@ -110,7 +116,7 @@ AudioSndio::AudioSndio(bool & _success_ful, Mixer * _mixer) :
return;
}
_success_ful = TRUE;
_success_ful = true;
}
@@ -160,7 +166,7 @@ void AudioSndio::run( void )
int_sample_t * outbuf =
new int_sample_t[mixer()->framesPerPeriod() * channels()];
while( TRUE )
while( true )
{
const fpp_t frames = getNextBuffer( temp );
if( !frames )
@@ -169,7 +175,7 @@ void AudioSndio::run( void )
}
uint bytes = convertToS16( temp, frames,
mixer()->masterGain(), outbuf, FALSE );
mixer()->masterGain(), outbuf, m_convertEndian );
if( sio_write( m_hdl, outbuf, bytes ) != bytes )
{
break;

View File

@@ -0,0 +1,273 @@
/* runtime/weak dynamic JACK linking
*
* (C) 2014 Robin Gareus <robin@gareus.org>
*
* 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, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "AudioWeakJack.h"
#ifndef USE_WEAK_JACK
int have_libjack (void) {
return 0;
}
#else
#include <stdio.h>
#include <string.h>
#include <assert.h>
#ifdef _WIN32
#include <windows.h>
#else
#include <dlfcn.h>
#endif
static void* lib_open(const char* const so) {
#ifdef _WIN32
return (void*) LoadLibraryA(so);
#else
return dlopen(so, RTLD_NOW|RTLD_LOCAL);
#endif
}
static void* lib_symbol(void* const lib, const char* const sym) {
#ifdef _WIN32
return (void*) GetProcAddress((HMODULE)lib, sym);
#else
return dlsym(lib, sym);
#endif
}
#if _MSC_VER && !__INTEL_COMPILER
typedef void * pvoid_t;
#define MAPSYM(SYM, FAIL) _j._ ## SYM = (func_t)lib_symbol(lib, "jack_" # SYM); \
if (!_j._ ## SYM) err |= FAIL;
#elif defined NDEBUG
typedef void * __attribute__ ((__may_alias__)) pvoid_t;
#define MAPSYM(SYM, FAIL) *(pvoid_t *)(&_j._ ## SYM) = lib_symbol(lib, "jack_" # SYM); \
if (!_j._ ## SYM) err |= FAIL;
#else
typedef void * __attribute__ ((__may_alias__)) pvoid_t;
#define MAPSYM(SYM, FAIL) *(pvoid_t *)(&_j._ ## SYM) = lib_symbol(lib, "jack_" # SYM); \
if (!_j._ ## SYM) { \
if (FAIL) { \
fprintf(stderr, "*** WEAK-JACK: required symbol 'jack_%s' was not found\n", "" # SYM); \
} \
err |= FAIL; \
}
#endif
typedef void (* func_t) (void);
/* function pointers to the real jack API */
static struct WeakJack {
func_t _client_open; // special case due to varargs
#define JCFUN(ERR, RTYPE, NAME, RVAL) func_t _ ## NAME ;
#define JPFUN(ERR, RTYPE, NAME, DEF, ARGS, RVAL) func_t _ ## NAME ;
#define JXFUN(ERR, RTYPE, NAME, DEF, ARGS, CODE) func_t _ ## NAME ;
#define JVFUN(ERR, NAME, DEF, ARGS, CODE) func_t _ ## NAME ;
#include "AudioWeakJack.def"
#undef JCFUN
#undef JPFUN
#undef JXFUN
#undef JVFUN
} _j;
static int _status = -1;
__attribute__((constructor))
static void init_weak_jack(void)
{
void* lib;
int err = 0;
#ifndef NDEBUG
fprintf(stderr, "*** WEAK-JACK: initializing\n");
#endif
memset(&_j, 0, sizeof(_j));
#ifdef __APPLE__
lib = lib_open("libjack.dylib");
if (!lib) {
lib = lib_open("/usr/local/lib/libjack.dylib");
}
#elif (defined _WIN32)
# ifdef __x86_64__
lib = lib_open("libjack64.dll");
# else
lib = lib_open("libjack.dll");
# endif
#else
lib = lib_open("libjack.so.0");
#endif
if (!lib) {
#ifndef NDEBUG
fprintf(stderr, "*** WEAK-JACK: libjack was not found\n");
#endif
_status = -2;
return;
}
/* found library, now lookup functions */
MAPSYM(client_open, 2)
#define JCFUN(ERR, RTYPE, NAME, RVAL) MAPSYM(NAME, ERR)
#define JPFUN(ERR, RTYPE, NAME, DEF, ARGS, RVAL) MAPSYM(NAME, ERR)
#define JXFUN(ERR, RTYPE, NAME, DEF, ARGS, CODE) MAPSYM(NAME, ERR)
#define JVFUN(ERR, NAME, DEF, ARGS, CODE) MAPSYM(NAME, ERR)
#include "AudioWeakJack.def"
#undef JCFUN
#undef JPFUN
#undef JXFUN
#undef JVFUN
/* if a required symbol is not found, disable JACK completly */
if (err) {
_j._client_open = NULL;
}
_status = err;
#ifndef NDEBUG
fprintf(stderr, "*** WEAK-JACK: %s. (%d)\n", err ? "jack is not available" : "OK", _status);
#endif
}
int have_libjack (void) {
if (_status == -1) {
init_weak_jack();
}
return _status;
}
/*******************************************************************************
* helper macros
*/
#if defined(__GNUC__) && (__GNUC__ > 2) && !defined(NDEBUG)
#define likely(expr) (__builtin_expect (!!(expr), 1))
#else
#define likely(expr) (expr)
#endif
#ifndef NDEBUG
# define WJACK_WARNING(NAME) \
fprintf(stderr, "*** WEAK-JACK: function 'jack_%s' ignored\n", "" # NAME);
#else
# define WJACK_WARNING(NAME) ;
#endif
/******************************************************************************
* JACK API wrapper functions.
*
* if a function pointer is set in the static struct WeakJack _j,
* the function is called directly.
* Otherwise a dummy NOOP implementation is provided.
* The latter is mainly for compile-time warnings.
*
* If libjack is not found, jack_client_open() will fail.
* In that case the application should not call any other libjack
* functions. Hence a real implementation is not needed.
* (jack ringbuffer may be an exception for some apps)
*/
/* dedicated support for jack_client_open(,..) variable arg function macro */
func_t WJACK_get_client_open(void) {
if (_status == -1) {
init_weak_jack();
}
return _j._client_open;
}
/* callback to set status */
jack_client_t * WJACK_no_client_open (const char *client_name, jack_options_t options, jack_status_t *status, ...) {
WJACK_WARNING(client_open);
if (status) { *status = JackFailure; }
return NULL;
}
/*******************************************************************************
* Macros to wrap jack API
*/
/* abstraction for jack_client functions
* rtype jack_function_name (jack_client_t *client) { return rval; }
*/
#define JCFUN(ERR, RTYPE, NAME, RVAL) \
RTYPE WJACK_ ## NAME (jack_client_t *client) { \
if likely(_j._ ## NAME) { \
return ((RTYPE (*)(jack_client_t *client)) _j._ ## NAME)(client); \
} else { \
WJACK_WARNING(NAME) \
return RVAL; \
} \
}
/* abstraction for NOOP functions with return value
* rtype jack_function_name (ARGS) { return rval; }
*/
#define JPFUN(ERR, RTYPE, NAME, DEF, ARGS, RVAL) \
RTYPE WJACK_ ## NAME DEF { \
if likely(_j._ ## NAME) { \
return ((RTYPE (*)DEF) _j._ ## NAME) ARGS; \
} else { \
WJACK_WARNING(NAME) \
return RVAL; \
} \
}
/* abstraction for functions that need custom code.
* e.g. functions with return-value-pointer args,
* use CODE to initialize value
*
* rtype jack_function_name (ARGS) { CODE }
*/
#define JXFUN(ERR, RTYPE, NAME, DEF, ARGS, CODE) \
RTYPE WJACK_ ## NAME DEF { \
if likely(_j._ ## NAME) { \
return ((RTYPE (*)DEF) _j._ ## NAME) ARGS; \
} else { \
WJACK_WARNING(NAME) \
CODE \
} \
}
/* abstraction for void functions with return-value-pointer args
* void jack_function_name (ARGS) { CODE }
*/
#define JVFUN(ERR, NAME, DEF, ARGS, CODE) \
void WJACK_ ## NAME DEF { \
if likely(_j._ ## NAME) { \
((void (*)DEF) _j._ ## NAME) ARGS; \
} else { \
WJACK_WARNING(NAME) \
CODE \
} \
}
#include "AudioWeakJack.def"
#undef JCFUN
#undef JPFUN
#undef JXFUN
#undef JVFUN
#endif // end USE_WEAK_JACK

View File

@@ -57,7 +57,6 @@
#include <signal.h>
#include "MainApplication.h"
#include "MemoryManager.h"
#include "ConfigManager.h"
#include "NotePlayHandle.h"
#include "embed.h"
@@ -203,7 +202,6 @@ void fileCheck( QString &file )
int main( int argc, char * * argv )
{
// initialize memory managers
MemoryManager::init();
NotePlayHandleManager::init();
// intialize RNG
@@ -930,9 +928,6 @@ int main( int argc, char * * argv )
Engine::destroy();
}
// cleanup memory managers
MemoryManager::cleanup();
// ProjectRenderer::updateConsoleProgress() doesn't return line after render
if( coreOnly )
{

View File

@@ -615,7 +615,7 @@ char * MidiApple::getFullName(MIDIEndpointRef &endpoint_ref)
char * deviceName = getName(device);
char * endPointName = getName(endpoint_ref);
qDebug("device name='%s' endpoint name='%s'",deviceName,endPointName);
char * fullName = (char *)malloc(strlen(deviceName) + strlen(endPointName)+1);
char * fullName = (char *)malloc(strlen(deviceName) + strlen(":") + strlen(endPointName)+1);
sprintf(fullName, "%s:%s", deviceName,endPointName);
return fullName;
}

View File

@@ -27,8 +27,8 @@
#ifdef LMMS_HAVE_SNDIO
#include <QtGui/QLabel>
#include <QtGui/QLineEdit>
#include <QLabel>
#include <QLineEdit>
#ifdef LMMS_HAVE_STDLIB_H
#include <stdlib.h>
@@ -42,7 +42,7 @@
MidiSndio::MidiSndio( void ) :
MidiClientRaw(),
m_quit( FALSE )
m_quit( false )
{
QString dev = probeDevice();
@@ -52,7 +52,7 @@ MidiSndio::MidiSndio( void ) :
}
else
{
m_hdl = mio_open( dev.toAscii().data(), MIO_IN | MIO_OUT, 0 );
m_hdl = mio_open( dev.toLatin1().constData(), MIO_IN | MIO_OUT, 0 );
}
if( m_hdl == NULL )
@@ -69,7 +69,7 @@ MidiSndio::~MidiSndio()
{
if( isRunning() )
{
m_quit = TRUE;
m_quit = true;
wait( 1000 );
terminate();
}
@@ -97,7 +97,7 @@ void MidiSndio::run( void )
char buf[0x100], *p;
size_t n;
int ret;
while( m_quit == FALSE && m_hdl )
while( m_quit == false && m_hdl )
{
nfds = mio_pollfd( m_hdl, &pfd, POLLIN );
ret = poll( &pfd, nfds, 100 );

View File

@@ -319,6 +319,16 @@ void AutomationPatternView::paintEvent( QPaintEvent * )
float *values = m_pat->valuesAfter( it.key() );
float nextValue;
if( m_pat->progressionType() == AutomationPattern::DiscreteProgression )
{
nextValue = it.value();
}
else
{
nextValue = ( it + 1 ).value();
}
QPainterPath path;
QPointF origin = QPointF( x_base + it.key() * ppTick, 0.0f );
path.moveTo( origin );
@@ -332,7 +342,7 @@ void AutomationPatternView::paintEvent( QPaintEvent * )
path.lineTo( QPointF( x, value ) );
}
path.lineTo( x_base + ( ( it + 1 ).key() ) * ppTick, values[ ( it + 1 ).key() - 1 - it.key() ] );
path.lineTo( x_base + ( ( it + 1 ).key() ) * ppTick, nextValue );
path.lineTo( x_base + ( ( it + 1 ).key() ) * ppTick, 0.0f );
path.lineTo( origin );

View File

@@ -382,6 +382,10 @@ void FxMixerView::deleteChannel(int index)
// remember selected line
int selLine = m_currentFxLine->channelIndex();
// in case the deleted channel is soloed or the remaining
// channels will be left in a muted state
Engine::fxMixer()->clearChannel(index);
// delete the real channel
Engine::fxMixer()->deleteChannel(index);

View File

@@ -33,7 +33,12 @@
MainApplication::MainApplication(int& argc, char** argv) :
QApplication(argc, argv),
m_queuedFile() {}
m_queuedFile()
{
#if defined(LMMS_BUILD_WIN32) && QT_VERSION >= 0x050000
installNativeEventFilter(this);
#endif
}
bool MainApplication::event(QEvent* event)
{
@@ -64,6 +69,7 @@ bool MainApplication::event(QEvent* event)
}
#ifdef LMMS_BUILD_WIN32
// This can be moved into nativeEventFilter once Qt4 support has been dropped
bool MainApplication::winEventFilter(MSG* msg, long* result)
{
switch(msg->message)
@@ -85,4 +91,16 @@ bool MainApplication::winEventFilter(MSG* msg, long* result)
return false;
}
}
#if QT_VERSION >= 0x050000
bool MainApplication::nativeEventFilter(const QByteArray& eventType,
void* message, long* result)
{
if(eventType == "windows_generic_MSG")
{
return winEventFilter(static_cast<MSG *>(message), result);
}
return false;
}
#endif
#endif

Some files were not shown because too many files have changed in this diff Show More