Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
psycha0s committed Apr 17, 2015
2 parents d50b987 + 3ae9090 commit 6761c8a
Show file tree
Hide file tree
Showing 29 changed files with 219 additions and 314 deletions.
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ project(${PROJECT_NAME})

# Project version
set(VERSION_MAJOR 1)
set(VERSION_MINOR 0)
set(VERSION_PATCH 2)
set(VERSION_MINOR 1)
set(VERSION_PATCH 0)

# Set plugin shared library base name
set(PLUGIN_BASENAME ${PROJECT_NAME}-plugin)
Expand Down
2 changes: 1 addition & 1 deletion README
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ Building the source
mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE="Release" -DCMAKE_INSTALL_PREFIX=/opt/airwave -DVSTSDK_PATH=${HOME}/VST3\ SDK ..
make
make install
sudo make install

Of course, you can change the CMAKE_INSTALL_PREFIX as you like.

Expand Down
101 changes: 56 additions & 45 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,48 +2,6 @@
Airwave is a [WINE](https://www.winehq.org/)-based VST bridge, that allows for the use of Windows 32- and 64-bit VST 2.4 audio plugins with Linux VST hosts.
Due to the use of shared memory, only one extra copying is made for each data transfer. Airwave also uses the XEMBED protocol to correctly embed the plugin editor into the host window.

## Compatibility
The following list is not complete. It contains only plugins, that have been tested by me or by people, who sent me a report.

VST-Plugins | works? | Notes |
------------:|:----------:|:-------|
Blue Cat Audio Oscilloscope Multi | no | doesn't work with wine
Credland Audio BigKick | no | doesn't work with wine
FabFilter Total bundle | yes | haven't tested them all
Image-Line Harmless | yes |
Image-Line Sytrus | yes |
LennarDigital Sylenth1 | no | doesn't work with wine
LePou Plugins | yes | LeCab2 has slight GUI redrawing issues
NI Absynth | yes |
NI FM8 | yes |
NI Guitar Rig 5 | yes | activation doesn't work
NI Kontakt 5 | mostly | up to v5.3.1, can import libraries only in Windows XP mode
NI Massive | yes | only 32-bit
NI Reaktor 5 | yes |
Peavey Revalver Mark III.V | yes |
ReFX Nexus2 | yes |
ReFX Vanguard | yes |
Reveal Sound Spire | yes | starting form 1.0.19 the GUI doesn't appear (wine issue)
Sonic Academy A.N.A. | yes |
Sonic Academy KICK | yes |
Smartelectronix s(M)exoscope | yes |
Synth1 by Ichiro Toda | yes |
Tone2 FireBird | yes |
Tone2 Nemesis | yes |
Tone2 Saurus | yes |
u-he A.C.E. | yes | Linux version is also available
u-he Bazille | yes | Linux version is also available
u-he Diva | yes | Linux version is also available
u-he Hive | yes | Linux version is also available
u-he Presswerk | yes | Linux version is also available
u-he Satin | yes | Linux version is also available
u-he Uhbik | yes | Linux version is also available
u-he Zebra2 | yes | Linux version is also available
Variety of Sound plugins | yes |
Voxengo SPAN | yes |
Voxengo SPAN Pro | mostly | inter plugin routing doesn't work (architecture issue)
Xfer Serum | partly | the GUI doesn't appear (wine issue), but audio works

## Requirements
- WINE, supporting XEMBED protocol (versions greater than 1.7.19 were tested,
but earlier versions also may work)
Expand Down Expand Up @@ -83,7 +41,7 @@ but earlier versions also may work)
mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE="Release" -DCMAKE_INSTALL_PREFIX=/opt/airwave -DVSTSDK_PATH=${HOME}/VST3\ SDK ..
make
make install
sudo make install
```
Of course, you can change the CMAKE_INSTALL_PREFIX as you like.
Expand All @@ -102,12 +60,65 @@ Of course, you can change the CMAKE_INSTALL_PREFIX as you like.
## Under the hood
The bridge consists of four components:
- Plugin endpoint (airwave-plugin-<arch>.so)
- Host endpoint (airwave-host-<arch>.exe.so and airwave-host-<arch>.exe launcher script)
- Plugin endpoint (airwave-plugin.so)
- Host endpoint (airwave-host-{arch}.exe.so and airwave-host-{arch}.exe launcher script)
- Configuration file (${XDG_CONFIG_PATH}/airwave/airwave.conf)
- GUI configurator (airwave-manager)
When the airwave-plugin is loaded by the VST host, it obtains its absolute path and use it as the key to get the linked VST DLL from the configuration. Then it starts the airwave-host process and passes the path to the linked VST file. The airwave-host loads the VST DLL and works as a fake VST host. Starting from this point, the airwave-plugin and airwave-host act together like a proxy, translating commands between the native VST host and the Windows VST plugin.
## Known issues
- Due to a bug in WINE, there is some hacking involved when embedding the editor window. There is a chance that you get a black window instead of the plugin GUI. Also some areas might not update correctly when increasing the window size. On some hosts (Bitwig Studio for example) this can be solved by closing and re-opening the plugin window.
## Compatibility
The following list is not complete. It contains only plugins, that have been tested by me or by people, who sent me a report.
VST-Plugins | works? | Notes |
------------:|:----------:|:-------|
AlgoMusic CZythia | yes |
Aly James LAB OB-Xtreme | yes |
Blue Cat Audio Oscilloscope Multi | no | doesn't work with wine
Credland Audio BigKick | no | doesn't work with wine
FabFilter Total bundle | yes | haven't tested them all
Green Oak Software Crystal | yes |
Image-Line Harmless | yes |
Image-Line Sytrus | yes |
LennarDigital Sylenth1 | no | doesn't work with wine
LePou Plugins | yes | LeCab2 has slight GUI redrawing issues
NI Absynth | yes |
NI FM8 | yes |
NI Guitar Rig 5 | yes | activation doesn't work
NI Kontakt 5 | mostly | up to v5.3.1, can import libraries only in Windows XP mode
NI Massive | yes | only 32-bit
NI Reaktor 5 | yes |
Magnus Choir | yes |
Martin Lüders pg8x | yes |
Meesha Damatriks | yes |
Odo Synths Double Six | partly | GUI doesn't show, but presets are available and functional
Peavey Revalver Mark III.V | yes |
ReFX Nexus2 | yes |
ReFX Vanguard | yes |
Reveal Sound Spire | yes | starting form 1.0.19 the GUI doesn't appear (wine issue)
Sonic Academy A.N.A. | yes |
Sonic Academy KICK | yes |
Sonic Cat LFX-1310 | yes |
Sonic Charge Cyclone | yes |
Smartelectronix s(M)exoscope | yes |
SQ8L by Siegfried Kullmann | yes |
SuperWave P8 | yes |
Synth1 by Ichiro Toda | yes |
Tone2 FireBird | yes |
Tone2 Nemesis | yes |
Tone2 Saurus | yes |
u-he A.C.E. | yes | Linux version is also available
u-he Bazille | yes | Linux version is also available
u-he Diva | yes | Linux version is also available
u-he Hive | yes | Linux version is also available
u-he Presswerk | yes | Linux version is also available
u-he Satin | yes | Linux version is also available
u-he Uhbik | yes | Linux version is also available
u-he Zebra2 | yes | Linux version is also available
Variety of Sound plugins | yes |
Voxengo SPAN | yes |
Voxengo SPAN Pro | mostly | inter plugin routing doesn't work (architecture issue)
Xfer Serum | no | the GUI doesn't appear (wine issue), but audio works
63 changes: 10 additions & 53 deletions src/common/dataport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,7 @@ bool DataPort::create(size_t frameSize)
return false;
}

ControlBlock* control = controlBlock();
sem_init(&control->request, 1, 0);
sem_init(&control->response, 1, 0);
new (controlBlock()) ControlBlock;

frameSize_ = frameSize;
return true;
Expand Down Expand Up @@ -89,9 +87,9 @@ void DataPort::disconnect()
{
if(!isNull()) {
if(!isConnected()) {
ControlBlock* control = controlBlock();
sem_destroy(&control->request);
sem_destroy(&control->response);
// ControlBlock* control = controlBlock();
// sem_destroy(&control->request);
// sem_destroy(&control->response);
}

shmdt(buffer_);
Expand Down Expand Up @@ -142,31 +140,27 @@ void* DataPort::frameBuffer()

void DataPort::sendRequest()
{
if(!isNull()) {
if(sem_post(&controlBlock()->request) != 0)
ERROR("sem_post() call failed: %s", strerror(errno));
}
if(!isNull())
controlBlock()->request.post();
}


void DataPort::sendResponse()
{
if(!isNull()) {
if(sem_post(&controlBlock()->response) != 0)
ERROR("sem_post() call failed: %s", strerror(errno));
}
if(!isNull())
controlBlock()->response.post();
}


bool DataPort::waitRequest(int msecs)
{
return waitForReady(&controlBlock()->request, msecs);
return controlBlock()->request.wait(msecs);
}


bool DataPort::waitResponse(int msecs)
{
return waitForReady(&controlBlock()->response, msecs);
return controlBlock()->response.wait(msecs);
}


Expand All @@ -176,41 +170,4 @@ DataPort::ControlBlock* DataPort::controlBlock()
}


bool DataPort::waitForReady(sem_t* semaphore, int msecs)
{
if(isNull())
return false;

if(msecs < 0) {
if(sem_wait(semaphore) != 0) {
ERROR("sem_wait() call failed: %d", errno);
return false;
}
}
else {
int seconds = msecs / 1000;
msecs %= 1000;

timespec tm;
clock_gettime(CLOCK_REALTIME, &tm);
tm.tv_sec += seconds;
tm.tv_nsec += msecs * 1000000;

if(tm.tv_nsec >= 1000000000L) {
tm.tv_sec++;
tm.tv_nsec -= 1000000000L;
}

if(sem_timedwait(semaphore, &tm) != 0) {
if(errno != ETIMEDOUT)
ERROR("sem_timedwait() call failed: %d", errno);

return false;
}
}

return true;
}


} // namespace Airwave
9 changes: 4 additions & 5 deletions src/common/dataport.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#ifndef COMMON_DATAPORT_H
#define COMMON_DATAPORT_H

#include <semaphore.h>
#include "common/event.h"
#include "common/types.h"


Expand Down Expand Up @@ -35,16 +35,15 @@ class DataPort {

private:
struct ControlBlock {
sem_t request;
sem_t response;
} __attribute__((packed));
Event request;
Event response;
};

int id_;
size_t frameSize_;
void* buffer_;

ControlBlock* controlBlock();
bool waitForReady(sem_t* semaphore, int msecs = -1);
};


Expand Down
59 changes: 59 additions & 0 deletions src/common/event.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#include "event.h"

#include <errno.h>
#include <syscall.h>
#include <time.h>
#include <unistd.h>
#include <linux/futex.h>


#define futex_wait(futex, count, timeout) \
(syscall(SYS_futex, futex, FUTEX_WAIT, count, timeout, nullptr, 0) == 0)

#define futex_post(futex, count) \
(syscall(SYS_futex, futex, FUTEX_WAKE, count, nullptr, nullptr, 0) == 0)


Event::Event() :
count_(0)
{
}


Event::~Event()
{
// FIXME The current implementation is not correct as it wakes only the one waiter.
futex_post(&count_, 1);
}


bool Event::wait(int msecs)
{
timespec* timeout = nullptr;
timespec tm;

if(msecs >= 0) {
int seconds = msecs / 1000;
msecs %= 1000;

tm.tv_sec = seconds;
tm.tv_nsec = msecs * 1000000;

timeout = &tm;
}

while(count_ == 0) {
if(!futex_wait(&count_, 0, timeout) && errno != EWOULDBLOCK)
return false;
}

count_--;
return true;
}


void Event::post()
{
count_++;
futex_post(&count_, 1);
}
26 changes: 26 additions & 0 deletions src/common/event.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#ifndef COMMON_EVENT_H
#define COMMON_EVENT_H

#include <atomic>

#ifdef bool
#undef bool
#endif


class Event {
public:
static const int kInfinite = -1;

Event();
~Event();

bool wait(int msecs = kInfinite);
void post();

private:
std::atomic<int> count_;
};


#endif // COMMON_EVENT_H
Loading

0 comments on commit 6761c8a

Please sign in to comment.