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
This commit is contained in:
Lukas W
2017-11-07 10:58:52 +01:00
73 changed files with 2854 additions and 530 deletions

3
.gitmodules vendored
View File

@@ -1,3 +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

@@ -16,6 +16,7 @@ matrix:
- 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-qt58-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,7 +1,7 @@
#!/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
libasound2-dev libjack-dev libsdl-dev libsamplerate0-dev libstk0-dev stk
libfluidsynth-dev portaudio19-dev g++-multilib libfltk1.3-dev
libgig-dev libsoundio-dev"
@@ -11,7 +11,7 @@ VST_PACKAGES="wine-dev libqt5x11extras5-dev qtbase5-private-dev libxcb-util0-dev
PACKAGES="$PACKAGES $VST_PACKAGES libjack0"
if [ $QT5 ]; then
PACKAGES="$PACKAGES qtbase5-dev qttools5-dev-tools qttools5-dev"
PACKAGES="$PACKAGES qt58base qt58translations qt58tools"
else
PACKAGES="$PACKAGES libqt4-dev"
fi

View File

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

View File

@@ -20,7 +20,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 +30,7 @@ SET(PROJECT_COPYRIGHT "2008-${PROJECT_YEAR} ${PROJECT_AUTHOR}")
SET(VERSION_MAJOR "1")
SET(VERSION_MINOR "2")
SET(VERSION_RELEASE "0")
SET(VERSION_STAGE "rc3")
SET(VERSION_STAGE "rc4")
SET(VERSION_BUILD "0")
SET(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_RELEASE}")
IF(VERSION_STAGE)
@@ -51,6 +51,7 @@ OPTION(WANT_CAPS "Include C* Audio Plugin Suite (LADSPA plugins)" ON)
OPTION(WANT_CARLA "Include Carla plugin" ON)
OPTION(WANT_CMT "Include Computer Music Toolkit LADSPA plugins" ON)
OPTION(WANT_JACK "Include JACK (Jack Audio Connection Kit) support" ON)
OPTION(WANT_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 +85,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>")
@@ -157,6 +160,9 @@ IF(WANT_QT5)
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()
@@ -369,8 +375,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")
@@ -429,7 +443,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
View 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,170 @@
#!/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}"
}
# 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="$(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 )"
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
QT_X11_NO_NATIVE_MENUBAR=1 QT_AUTO_SCREEN_SCALE_FACTOR=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"
# 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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 643 B

After

Width:  |  Height:  |  Size: 808 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 637 B

After

Width:  |  Height:  |  Size: 799 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 641 B

After

Width:  |  Height:  |  Size: 803 B

View File

@@ -28,7 +28,11 @@
#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>

View File

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

159
include/AudioWeakJack.def Normal file
View File

@@ -0,0 +1,159 @@
/* 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)
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);)
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

@@ -30,9 +30,6 @@
#include "export.h"
#include "lmms_basics.h"
const int BM_INITIAL_BUFFERS = 512;
//const int BM_INCREMENT = 64;
class EXPORT BufferManager
{
public:
@@ -46,17 +43,6 @@ public:
const f_cnt_t offset = 0 );
#endif
static void release( sampleFrame * buf );
static void refresh();
// static void extend( int c );
private:
static sampleFrame ** s_available;
static AtomicInt s_availableIndex;
static sampleFrame ** s_released;
static AtomicInt s_releasedIndex;
// static QReadWriteLock s_mutex;
static int s_size;
};
#endif

View File

@@ -25,13 +25,22 @@
#ifndef MAINAPPLICATION_H
#define MAINAPPLICATION_H
#include "lmmsconfig.h"
#include <QApplication>
#ifdef LMMS_BUILD_WIN32
#include <windows.h>
#endif
class MainApplication : public QApplication
{
public:
MainApplication(int& argc, char** argv);
bool event(QEvent* event);
#ifdef LMMS_BUILD_WIN32
bool winEventFilter(MSG* msg, long* result);
#endif
inline QString& queuedFile()
{
return m_queuedFile;

View File

@@ -249,11 +249,4 @@ signals:
} ;
class AutoSaveThread : public QThread
{
Q_OBJECT
public:
void run();
} ;
#endif

View File

@@ -31,7 +31,7 @@
class MemoryHelper {
public:
static void* alignedMalloc( int );
static void* alignedMalloc( size_t );
static void alignedFree( void* );

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,41 @@
#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;
int m_chunks;
QMutex m_mutex;
MemoryPool() :
m_pool( NULL ),
m_free( NULL ),
m_chunks( 0 )
{}
MemoryPool( int chunks ) :
m_chunks( chunks )
{
m_free = (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;
template<typename T>
struct MmAllocator
{
typedef T value_type;
template<class U> struct rebind { typedef MmAllocator<U> other; };
static PointerInfoMap s_pointerInfo;
static QMutex s_pointerMutex;
T* allocate( std::size_t n )
{
return reinterpret_cast<T*>( MemoryManager::alloc( sizeof(T) * n ) );
}
void deallocate( T* p, std::size_t )
{
MemoryManager::free( p );
}
typedef std::vector<T, MmAllocator<T> > vector;
};
@@ -124,36 +85,8 @@ static void operator delete[] ( void * ptr ) \
}
// for use in cases where overriding new/delete isn't a possibility
#define MM_ALLOC( type, count ) (type*) MemoryManager::alloc( sizeof( type ) * count )
#define MM_ALLOC( type, count ) reinterpret_cast<type*>( MemoryManager::alloc( sizeof( type ) * count ) )
// 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

@@ -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,8 @@
#include <QtCore/QList>
#include <QtCore/QMutex>
#include "MemoryManager.h"
#include "ThreadableJob.h"
#include "lmms_basics.h"
@@ -142,20 +144,17 @@ public:
void releaseBuffer();
sampleFrame * buffer()
{
return m_playHandleBuffer;
}
sampleFrame * buffer();
private:
Type m_type;
f_cnt_t m_offset;
QThread* m_affinity;
QMutex m_processingLock;
sampleFrame * m_playHandleBuffer;
sampleFrame* m_playHandleBuffer;
bool m_bufferReleased;
bool m_usesBuffer;
AudioPort * m_audioPort;
} ;

View File

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

View File

@@ -624,6 +624,11 @@ public:
fetchAndProcessNextMessage();
}
}
static bool isMainThreadWaiting()
{
return waitDepthCounter() > 0;
}
#endif
virtual bool processMessage( const message & _m ) = 0;
@@ -660,6 +665,14 @@ protected:
private:
#ifndef BUILD_REMOTE_PLUGIN_CLIENT
static int & waitDepthCounter()
{
static int waitDepth = 0;
return waitDepth;
}
#endif
#ifdef SYNC_WITH_SHM_FIFO
shmFifo * m_in;
shmFifo * m_out;
@@ -1104,6 +1117,26 @@ RemotePluginBase::message RemotePluginBase::waitForMessage(
_busy_waiting = QThread::currentThread() ==
QCoreApplication::instance()->thread();
}
struct WaitDepthCounter
{
WaitDepthCounter( int & depth, bool busy ) :
m_depth( depth ),
m_busy( busy )
{
if( m_busy ) { ++m_depth; }
}
~WaitDepthCounter()
{
if( m_busy ) { --m_depth; }
}
int & m_depth;
bool m_busy;
};
WaitDepthCounter wdc( waitDepthCounter(), _busy_waiting );
#endif
while( !isInvalid() )
{

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

@@ -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

@@ -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

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

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

@@ -34,20 +34,15 @@ 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})
ADD_CUSTOM_COMMAND(
@@ -55,8 +50,6 @@ ADD_CUSTOM_COMMAND(
COMMAND ${WINE_CXX}
ARGS -I${CMAKE_BINARY_DIR}
-I${CMAKE_SOURCE_DIR}/include
-I${CMAKE_INSTALL_PREFIX}/include/wine/windows
-I${CMAKE_INSTALL_PREFIX}/include
-I${WINE_INCLUDE_BASE_DIR}
-L${WINE_LIBRARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/RemoteVstPlugin.cpp
@@ -64,6 +57,7 @@ ADD_CUSTOM_COMMAND(
-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

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() );

View File

@@ -1,4 +1,5 @@
include(ExternalProject)
set(CMAKE_C_FLAGS "")
set(CMAKE_CXX_FLAGS "")
IF(QT5 AND LMMS_BUILD_LINUX)
set(BUILD_SHARED_LIBS OFF)
@@ -6,3 +7,5 @@ IF(QT5 AND LMMS_BUILD_LINUX)
ELSE()
add_library(qx11embedcontainer STATIC /dev/null)
ENDIF()
ADD_SUBDIRECTORY(rpmalloc)

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

@@ -0,0 +1,30 @@
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")
target_compile_definitions(rpmalloc
PRIVATE -DENABLE_ASSERTS=1 -DENABLE_VALIDATE_ARGS=1
)
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,13 +10,12 @@ 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++")
ENDIF()
ADD_SUBDIRECTORY(3rdparty)
ADD_SUBDIRECTORY(core)
ADD_SUBDIRECTORY(gui)
ADD_SUBDIRECTORY(tracks)
@@ -148,7 +149,9 @@ SET(LMMS_REQUIRED_LIBS ${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)
@@ -156,6 +159,14 @@ TARGET_LINK_LIBRARIES(lmms
${LMMS_REQUIRED_LIBS}
)
FOREACH(LIB ${LMMS_REQUIRED_LIBS})
GET_TARGET_PROPERTY(INCLUDE_DIRS ${LIB} INTERFACE_INCLUDE_DIRECTORIES)
if (INCLUDE_DIRS)
TARGET_INCLUDE_DIRECTORIES(lmmsobjs PRIVATE ${INCLUDE_DIRS})
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

@@ -1,6 +1,7 @@
/*
* BufferManager.cpp - A buffer caching/memory management system
*
* Copyright (c) 2017 Lukas W <lukaswhl/at/gmail.com>
* Copyright (c) 2014 Vesa Kivimäki <contact/dot/diizy/at/nbl/dot/fi>
* Copyright (c) 2006-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
@@ -25,56 +26,28 @@
#include "BufferManager.h"
#include "Engine.h"
#include "Mixer.h"
#include "MemoryManager.h"
sampleFrame ** BufferManager::s_available;
AtomicInt BufferManager::s_availableIndex = 0;
sampleFrame ** BufferManager::s_released;
AtomicInt BufferManager::s_releasedIndex = 0;
//QReadWriteLock BufferManager::s_mutex;
int BufferManager::s_size;
static fpp_t framesPerPeriod;
void BufferManager::init( fpp_t framesPerPeriod )
{
s_available = MM_ALLOC( sampleFrame*, BM_INITIAL_BUFFERS );
s_released = MM_ALLOC( sampleFrame*, BM_INITIAL_BUFFERS );
int c = framesPerPeriod * BM_INITIAL_BUFFERS;
sampleFrame * b = MM_ALLOC( sampleFrame, c );
for( int i = 0; i < BM_INITIAL_BUFFERS; ++i )
{
s_available[ i ] = b;
b += framesPerPeriod;
}
s_availableIndex = BM_INITIAL_BUFFERS - 1;
s_size = BM_INITIAL_BUFFERS;
::framesPerPeriod = framesPerPeriod;
}
sampleFrame * BufferManager::acquire()
{
if( s_availableIndex < 0 )
{
qFatal( "BufferManager: out of buffers" );
}
int i = s_availableIndex.fetchAndAddOrdered( -1 );
sampleFrame * b = s_available[ i ];
//qDebug( "acquired buffer: %p - index %d", b, i );
return b;
return MM_ALLOC( sampleFrame, ::framesPerPeriod );
}
void BufferManager::clear( sampleFrame * ab, const f_cnt_t frames,
const f_cnt_t offset )
void BufferManager::clear( sampleFrame *ab, const f_cnt_t frames, const f_cnt_t offset )
{
memset( ab + offset, 0, sizeof( *ab ) * frames );
}
#ifndef LMMS_DISABLE_SURROUND
void BufferManager::clear( surroundSampleFrame * ab, const f_cnt_t frames,
const f_cnt_t offset )
@@ -86,43 +59,6 @@ void BufferManager::clear( surroundSampleFrame * ab, const f_cnt_t frames,
void BufferManager::release( sampleFrame * buf )
{
if (buf == nullptr) return;
int i = s_releasedIndex.fetchAndAddOrdered( 1 );
s_released[ i ] = buf;
//qDebug( "released buffer: %p - index %d", buf, i );
MM_FREE( buf );
}
void BufferManager::refresh() // non-threadsafe, hence it's called periodically from mixer at a time when no other threads can interfere
{
if( s_releasedIndex == 0 ) return;
//qDebug( "refresh: %d buffers", int( s_releasedIndex ) );
int j = s_availableIndex;
for( int i = 0; i < s_releasedIndex; ++i )
{
++j;
s_available[ j ] = s_released[ i ];
}
s_availableIndex = j;
s_releasedIndex = 0;
}
/* // non-extensible for now
void BufferManager::extend( int c )
{
s_size += c;
sampleFrame ** tmp = MM_ALLOC( sampleFrame*, s_size );
MM_FREE( s_available );
s_available = tmp;
int cc = c * Engine::mixer()->framesPerPeriod();
sampleFrame * b = MM_ALLOC( sampleFrame, cc );
for( int i = 0; i < c; ++i )
{
s_available[ s_availableIndex.fetchAndAddOrdered( 1 ) + 1 ] = b;
b += Engine::mixer()->framesPerPeriod();
}
}*/

View File

@@ -1,3 +1,7 @@
IF(LMMS_HAVE_WEAKJACK)
set(WEAKJACK core/audio/AudioWeakJack.c)
ENDIF()
set(LMMS_SRCS
${LMMS_SRCS}
core/AutomatableModel.cpp
@@ -72,6 +76,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

@@ -519,7 +519,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

@@ -30,7 +30,7 @@
* Allocate a number of bytes and return them.
* @param byteNum is the number of bytes
*/
void* MemoryHelper::alignedMalloc( int byteNum )
void* MemoryHelper::alignedMalloc( size_t byteNum )
{
char *ptr, *ptr2, *aligned_ptr;
int align_mask = ALIGN_SIZE - 1;

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"
@@ -482,9 +483,6 @@ const surroundSampleFrame * Mixer::renderNextBuffer()
Controller::triggerFrameCounter();
AutomatableModel::incrementPeriodCounter();
// refresh buffer pool
BufferManager::refresh();
s_renderingThread = false;
m_profiler.finishPeriod( processingSampleRate(), m_framesPerPeriod );

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

@@ -24,16 +24,21 @@
#include "PlayHandle.h"
#include "BufferManager.h"
#include "Engine.h"
#include "Mixer.h"
#include <QtCore/QThread>
#include <QDebug>
#include <iterator>
PlayHandle::PlayHandle( const Type type, f_cnt_t offset ) :
m_type( type ),
m_offset( offset ),
m_affinity( QThread::currentThread() ),
m_playHandleBuffer( NULL ),
m_usesBuffer( true )
PlayHandle::PlayHandle(const Type type, f_cnt_t offset) :
m_type(type),
m_offset(offset),
m_affinity(QThread::currentThread()),
m_playHandleBuffer(BufferManager::acquire()),
m_bufferReleased(true),
m_usesBuffer(true)
{
}
@@ -48,8 +53,9 @@ void PlayHandle::doProcessing()
{
if( m_usesBuffer )
{
if( ! m_playHandleBuffer ) m_playHandleBuffer = BufferManager::acquire();
play( m_playHandleBuffer );
m_bufferReleased = false;
BufferManager::clear(m_playHandleBuffer, Engine::mixer()->framesPerPeriod());
play( buffer() );
}
else
{
@@ -60,6 +66,10 @@ void PlayHandle::doProcessing()
void PlayHandle::releaseBuffer()
{
BufferManager::release( m_playHandleBuffer );
m_playHandleBuffer = NULL;
m_bufferReleased = true;
}
sampleFrame* PlayHandle::buffer()
{
return m_bufferReleased ? nullptr : reinterpret_cast<sampleFrame*>(m_playHandleBuffer);
};

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

@@ -36,7 +36,7 @@ AudioPort::AudioPort( const QString & _name, bool _has_effect_chain,
FloatModel * volumeModel, FloatModel * panningModel,
BoolModel * mutedModel ) :
m_bufferUsage( false ),
m_portBuffer( NULL ),
m_portBuffer( BufferManager::acquire() ),
m_extOutputEnabled( false ),
m_nextFxChannel( 0 ),
m_name( "unnamed port" ),
@@ -57,6 +57,7 @@ AudioPort::~AudioPort()
setExtOutputEnabled( false );
Engine::mixer()->removeAudioPort( this );
delete m_effects;
BufferManager::release( m_portBuffer );
}
@@ -110,8 +111,7 @@ void AudioPort::doProcessing()
const fpp_t fpp = Engine::mixer()->framesPerPeriod();
// get a buffer for processing and clear it
m_portBuffer = BufferManager::acquire();
// clear the buffer
BufferManager::clear( m_portBuffer, fpp );
//qDebug( "Playhandles: %d", m_playHandles.size() );
@@ -225,8 +225,6 @@ void AudioPort::doProcessing()
// TODO: improve the flow here - convert to pull model
m_bufferUsage = false;
}
BufferManager::release( m_portBuffer ); // release buffer, we don't need it anymore
}

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

@@ -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

@@ -62,3 +62,27 @@ bool MainApplication::event(QEvent* event)
return QApplication::event(event);
}
}
#ifdef LMMS_BUILD_WIN32
bool MainApplication::winEventFilter(MSG* msg, long* result)
{
switch(msg->message)
{
case WM_STYLECHANGING:
if(msg->wParam == GWL_EXSTYLE)
{
// Prevent plugins making the main window transparent
STYLESTRUCT * style = reinterpret_cast<STYLESTRUCT *>(msg->lParam);
if(!(style->styleOld & WS_EX_LAYERED))
{
style->styleNew &= ~WS_EX_LAYERED;
}
*result = 0;
return true;
}
return false;
default:
return false;
}
}
#endif

View File

@@ -54,6 +54,7 @@
#include "PluginView.h"
#include "ProjectJournal.h"
#include "ProjectNotes.h"
#include "RemotePlugin.h"
#include "SetupDialog.h"
#include "SideBar.h"
#include "SongEditor.h"
@@ -1535,14 +1536,14 @@ void MainWindow::browseHelp()
void MainWindow::autoSave()
{
if( !Engine::getSong()->isExporting() &&
!Engine::getSong()->isLoadingProject() &&
!RemotePluginBase::isMainThreadWaiting() &&
!QApplication::mouseButtons() &&
( ConfigManager::inst()->value( "ui",
"enablerunningautosave" ).toInt() ||
! Engine::getSong()->isPlaying() ) )
( ConfigManager::inst()->value( "ui",
"enablerunningautosave" ).toInt() ||
! Engine::getSong()->isPlaying() ) )
{
AutoSaveThread * ast = new AutoSaveThread();
connect( ast, SIGNAL( finished() ), ast, SLOT( deleteLater() ) );
ast->start();
Engine::getSong()->saveProjectFile(ConfigManager::inst()->recoveryFile());
autoSaveTimerReset(); // Reset timer
}
else
@@ -1554,11 +1555,3 @@ void MainWindow::autoSave()
}
}
}
void AutoSaveThread::run()
{
Engine::getSong()->saveProjectFile(ConfigManager::inst()->recoveryFile());
}

View File

@@ -589,6 +589,7 @@ void AutomationEditor::mousePressEvent( QMouseEvent* mouseEvent )
m_editMode == DRAW ) ||
m_editMode == ERASE )
{
m_drawLastTick = pos_ticks;
m_pattern->addJournalCheckPoint();
// erase single value
if( it != time_map.end() )
@@ -680,6 +681,39 @@ void AutomationEditor::mouseReleaseEvent(QMouseEvent * mouseEvent )
void AutomationEditor::removePoints( int x0, int x1 )
{
int deltax = qAbs( x1 - x0 );
int x = x0;
int xstep;
if( deltax < 1 )
{
return;
}
if( x0 < x1 )
{
xstep = 1;
}
else
{
xstep = -1;
}
int i = 0;
while( i <= deltax )
{
m_pattern->removeValue( MidiTime( x ) );
x += xstep;
i += 1;
}
}
void AutomationEditor::mouseMoveEvent(QMouseEvent * mouseEvent )
{
QMutexLocker m( &m_patternMutex );
@@ -735,14 +769,13 @@ void AutomationEditor::mouseMoveEvent(QMouseEvent * mouseEvent )
( mouseEvent->buttons() & Qt::LeftButton &&
m_editMode == ERASE ) )
{
// int resolution needed to improve the sensitivity of
// the erase manoeuvre with zoom levels < 100%
int zoom = m_zoomingXModel.value();
int resolution = 1 + zoom * zoom;
for( int i = -resolution; i < resolution; ++i )
// removing automation point
if( pos_ticks < 0 )
{
m_pattern->removeValue( MidiTime( pos_ticks + i ) );
pos_ticks = 0;
}
removePoints( m_drawLastTick, pos_ticks );
Engine::getSong()->setModified();
}
else if( mouseEvent->buttons() & Qt::NoButton && m_editMode == DRAW )
{
@@ -1067,7 +1100,7 @@ inline void AutomationEditor::drawAutomationPoint( QPainter & p, timeMap::iterat
{
int x = xCoordOfTick( it.key() );
int y = yCoordOfLevel( it.value() );
const int outerRadius = qBound( 2, ( m_ppt * AutomationPattern::quantization() ) / 576, 5 ); // man, getting this calculation right took forever
const int outerRadius = qBound( 3, ( m_ppt * AutomationPattern::quantization() ) / 576, 5 ); // man, getting this calculation right took forever
p.setPen( QPen( vertexColor().lighter( 200 ) ) );
p.setBrush( QBrush( vertexColor() ) );
p.drawEllipse( x - outerRadius, y - outerRadius, outerRadius * 2, outerRadius * 2 );

View File

@@ -11,6 +11,7 @@
#cmakedefine LMMS_HAVE_ALSA
#cmakedefine LMMS_HAVE_FLUIDSYNTH
#cmakedefine LMMS_HAVE_JACK
#cmakedefine LMMS_HAVE_WEAKJACK
#cmakedefine LMMS_HAVE_MP3LAME
#cmakedefine LMMS_HAVE_OGGVORBIS
#cmakedefine LMMS_HAVE_OSS

View File

@@ -157,7 +157,8 @@ InstrumentTrack::~InstrumentTrack()
void InstrumentTrack::processAudioBuffer( sampleFrame* buf, const fpp_t frames, NotePlayHandle* n )
{
// we must not play the sound if this InstrumentTrack is muted...
if( isMuted() || ( n && n->isBbTrackMuted() ) || ! m_instrument )
if( isMuted() || ( Engine::getSong()->playMode() != Song::Mode_PlayPattern &&
n && n->isBbTrackMuted() ) || ! m_instrument )
{
return;
}
@@ -613,7 +614,10 @@ bool InstrumentTrack::play( const MidiTime & _start, const fpp_t _frames,
{
TrackContentObject * tco = getTCO( _tco_num );
tcos.push_back( tco );
bb_track = BBTrack::findBBTrack( _tco_num );
if (trackContainer() == (TrackContainer*)Engine::getBBTrackContainer())
{
bb_track = BBTrack::findBBTrack( _tco_num );
}
}
else
{

View File

@@ -213,28 +213,7 @@ Note * Pattern::addNote( const Note & _new_note, const bool _quant_pos )
}
instrumentTrack()->lock();
if( m_notes.size() == 0 || m_notes.back()->pos() <= new_note->pos() )
{
m_notes.push_back( new_note );
}
else
{
// simple algorithm for inserting the note between two
// notes with smaller and greater position
// maybe it could be optimized by starting in the middle and
// going forward or backward but note-inserting isn't that
// time-critical since it is usually not done while playing...
long new_note_abs_time = new_note->pos();
NoteVector::Iterator it = m_notes.begin();
while( it != m_notes.end() &&
( *it )->pos() < new_note_abs_time )
{
++it;
}
m_notes.insert( it, new_note );
}
m_notes.insert(std::upper_bound(m_notes.begin(), m_notes.end(), new_note, Note::lessThan), new_note);
instrumentTrack()->unlock();
checkType();
@@ -292,7 +271,7 @@ Note * Pattern::noteAtStep( int _step )
void Pattern::rearrangeAllNotes()
{
// sort notes by start time
qSort(m_notes.begin(), m_notes.end(), Note::lessThan );
std::sort(m_notes.begin(), m_notes.end(), Note::lessThan);
}

View File

@@ -587,7 +587,10 @@ bool SampleTrack::play( const MidiTime & _start, const fpp_t _frames,
return false;
}
tcos.push_back( getTCO( _tco_num ) );
bb_track = BBTrack::findBBTrack( _tco_num );
if (trackContainer() == (TrackContainer*)Engine::getBBTrackContainer())
{
bb_track = BBTrack::findBBTrack( _tco_num );
}
}
else
{