Skip to content

Commit

Permalink
Enable 64bit VSTs on Linux
Browse files Browse the repository at this point in the history
* Remove trial-and-error approach of detecting VST's machine types. Read PE
  headers instead.
* Add RemoteVstPlugin64 to AppImage
  • Loading branch information
lukas-w committed Jun 7, 2018
1 parent 3beac2c commit 9db8cbf
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 30 deletions.
14 changes: 9 additions & 5 deletions cmake/linux/package_linux.sh.in
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ EOL

chmod +x "${APPDIR}usr/bin/lmms"

# Per https://github.com/probonopd/linuxdeployqt/issues/129
# Per https://github.com/probonopd/linuxdeployqt/issues/129
unset LD_LIBRARY_PATH

# Ensure linuxdeployqt can find shared objects
Expand All @@ -139,13 +139,16 @@ fi

# Move executables so linuxdeployqt can find them
ZYNLIB="${APPDIR}usr/lib/lmms/RemoteZynAddSubFx"
VSTLIB="${APPDIR}usr/lib/lmms/RemoteVstPlugin32.exe.so"
VSTLIB32="${APPDIR}usr/lib/lmms/RemoteVstPlugin32.exe.so"
VSTLIB64="${APPDIR}usr/lib/lmms/RemoteVstPlugin64.exe.so"

ZYNBIN="${APPDIR}usr/bin/RemoteZynAddSubFx"
VSTBIN="${APPDIR}usr/bin/RemoteVstPlugin32.exe.so"
VSTBIN32="${APPDIR}usr/bin/RemoteVstPlugin32.exe.so"
VSTBIN64="${APPDIR}usr/bin/RemoteVstPlugin64.exe.so"

mv "$ZYNLIB" "$ZYNBIN"
mv "$VSTLIB" "$VSTBIN"
mv "$VSTLIB32" "$VSTBIN32"
mv "$VSTLIB64" "$VSTBIN64"

# Patch the desktop file
sed -i 's/.*Exec=.*/Exec=lmms.real/' "$DESKTOPFILE"
Expand All @@ -171,7 +174,8 @@ success "Bundled and relinked dependencies"

# Link to original location so lmms can find them
ln -sr "$ZYNBIN" "$ZYNLIB"
ln -sr "$VSTBIN" "$VSTLIB"
ln -sr "$VSTBIN32" "$VSTLIB32"
ln -sr "$VSTBIN64" "$VSTLIB64"

# Remove wine library conflict
rm -f "${APPDIR}/usr/lib/libwine.so.1"
Expand Down
3 changes: 1 addition & 2 deletions include/RemotePlugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -854,12 +854,11 @@ public slots:
}


bool m_failed;
private:
void resizeSharedProcessingMemory();


bool m_failed;

QProcess m_process;
ProcessWatcher m_watcher;

Expand Down
5 changes: 0 additions & 5 deletions plugins/vst_base/RemoteVstPlugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -785,11 +785,6 @@ bool RemoteVstPlugin::load( const std::string & _plugin_file )
{
DWORD error = GetLastError();
debugMessage( "LoadLibrary failed: " + GetErrorAsString(error) );
// give VstPlugin class a chance to start 32 bit version of RemoteVstPlugin
if( GetLastError() == ERROR_BAD_EXE_FORMAT )
{
sendMessage( IdVstBadDllFormat );
}
return false;
}

Expand Down
79 changes: 67 additions & 12 deletions plugins/vst_base/VstPlugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

#include "communication.h"

#include <QtCore/QtEndian>
#include <QtCore/QDebug>
#include <QDir>
#include <QFileInfo>
Expand Down Expand Up @@ -64,6 +65,54 @@
#include "templates.h"
#include "FileDialog.h"

namespace PE
{
// Utilities for reading PE file machine type
// See specification at https://msdn.microsoft.com/library/windows/desktop/ms680547(v=vs.85).aspx

enum MachineType : uint16_t
{
IMAGE_FILE_MACHINE_UNKNOWN = 0x0,
IMAGE_FILE_MACHINE_AMD64 = 0x8664,
IMAGE_FILE_MACHINE_I386 = 0x14c,
};

class FileInfo
{
public:
FileInfo(QString filePath)
: m_file(filePath)
{
m_file.open(QFile::ReadOnly);
m_map = m_file.map(0, m_file.size());
if (m_map == nullptr) {
throw std::runtime_error("Cannot map file");
}
}
~FileInfo()
{
m_file.unmap(m_map);
}

MachineType machineType()
{
int32_t peOffset = qFromLittleEndian(* reinterpret_cast<int32_t*>(m_map + 0x3C));
uchar* peSignature = m_map + peOffset;
if (memcmp(peSignature, "PE\0\0", 4)) {
throw std::runtime_error("Invalid PE file");
}
uchar * coffHeader = peSignature + 4;
uint16_t machineType = qFromLittleEndian(* reinterpret_cast<uint16_t*>(coffHeader));
return static_cast<MachineType>(machineType);
}

private:
QFile m_file;
uchar* m_map;
};

}

class vstSubWin : public QMdiSubWindow
{
public:
Expand Down Expand Up @@ -93,22 +142,32 @@ VstPlugin::VstPlugin( const QString & _plugin ) :
m_embedMethod( gui
? ConfigManager::inst()->vstEmbedMethod()
: "headless" ),
m_badDllFormat( false ),
m_version( 0 ),
m_currentProgram()
{
setSplittedChannels( true );

#ifdef LMMS_BUILD_WIN64
tryLoad( "RemoteVstPlugin64" );
if( m_badDllFormat )
PE::MachineType machineType;
try {
PE::FileInfo peInfo(_plugin);
machineType = peInfo.machineType();
} catch (std::runtime_error& e) {
qCritical() << "Error while determining PE file's machine type: " << e.what();
machineType = PE::IMAGE_FILE_MACHINE_UNKNOWN;
}

switch(machineType)
{
m_badDllFormat = false;
#endif
case PE::IMAGE_FILE_MACHINE_AMD64:
tryLoad( "RemoteVstPlugin64" );
break;
case PE::IMAGE_FILE_MACHINE_I386:
tryLoad( "RemoteVstPlugin32" );
#ifdef LMMS_BUILD_WIN64
break;
default:
m_failed = true;
return;
}
#endif

setTempo( Engine::getSong()->getTempo() );

Expand Down Expand Up @@ -390,10 +449,6 @@ bool VstPlugin::processMessage( const message & _m )
{
switch( _m.id )
{
case IdVstBadDllFormat:
m_badDllFormat = true;
break;

case IdVstPluginWindowID:
m_pluginWindowID = _m.getInt();
break;
Expand Down
2 changes: 0 additions & 2 deletions plugins/vst_base/VstPlugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,6 @@ public slots:
QSize m_pluginGeometry;
const QString m_embedMethod;

bool m_badDllFormat;

QString m_name;
int m_version;
QString m_vendorString;
Expand Down
1 change: 0 additions & 1 deletion plugins/vst_base/communication.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ enum VstRemoteMessageIDs

// remoteVstPlugin -> vstPlugin
IdVstFailedLoadingPlugin,
IdVstBadDllFormat,
IdVstPluginWindowID,
IdVstPluginEditorGeometry,
IdVstPluginName,
Expand Down
6 changes: 3 additions & 3 deletions src/core/RemotePlugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,10 @@ void ProcessWatcher::run()
{
fprintf( stderr,
"remote plugin died! invalidating now.\n" );

#ifndef SYNC_WITH_SHM_FIFO
m_plugin->invalidate();
#endif
}
}

Expand Down Expand Up @@ -464,9 +467,6 @@ void RemotePlugin::processFinished( int exitCode,
{
qCritical() << "Remote plugin exit code: " << exitCode;
}
#ifndef SYNC_WITH_SHM_FIFO
invalidate();
#endif
}

void RemotePlugin::processErrored( QProcess::ProcessError err )
Expand Down

0 comments on commit 9db8cbf

Please sign in to comment.