Skip to content

Commit

Permalink
Add macOS support
Browse files Browse the repository at this point in the history
  • Loading branch information
ShirasawaSama committed Oct 17, 2023
1 parent 8b79d83 commit b2ad233
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 41 deletions.
30 changes: 19 additions & 11 deletions src/Main.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
#include "plugin_host.h"
#include "audio_output.h"

#if JUCE_MAC
namespace juce { extern void initialiseNSApplication(); }
#endif

int main(int argc, char* argv[]) {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
Expand All @@ -14,14 +18,12 @@ int main(int argc, char* argv[]) {
manager.addDefaultFormats();
auto id = args->getValueForOption("-S|--scan");
if (id.isEmpty()) {
#ifdef JUCE_MAC
auto paths = manager.getFormat(0)->searchPathsForPlugins(juce::FileSearchPath(), true, true);
puts(juce::JSON::toString(paths).toRawUTF8());
juce::StringArray paths;
for (auto it : manager.getFormats()) {
paths.addArray(it->searchPathsForPlugins(juce::FileSearchPath(), true, true));
}
puts(juce::JSON::toString(paths, true).toRawUTF8());
return 0;
#else
std::cerr << "No any file specified.\n";
return -1;
#endif
} else if (id == "#") {
char path[512];
std::cin.getline(path, 512, 0);
Expand Down Expand Up @@ -58,6 +60,7 @@ int main(int argc, char* argv[]) {
puts(("$EIMHostScanner{{" + juce::JSON::toString(arr, true) + "}}EIMHostScanner$").toRawUTF8());
juce::shutdownJuce_GUI();
} else if (args->containsOption("-L|--load")) {
eim::streams::output_stream::preventStdout();
juce::initialiseJuce_GUI();
juce::JUCEApplicationBase::createInstance = eim::plugin_host::createInstance;
juce::JUCEApplicationBase::main(argc, (const char**)argv);
Expand All @@ -67,15 +70,17 @@ int main(int argc, char* argv[]) {
CoInitialize(nullptr);
#endif

juce::initialiseJuce_GUI();
juce::AudioDeviceManager deviceManager;
if (args->containsOption("-A|--all")) {
for (auto& it : deviceManager.getAvailableDeviceTypes()) {
it->scanForDevices();
for (auto& j : it->getDeviceNames()) {
std::cerr << "[" << it->getTypeName() << "] " << j << "$EIM$";
std::cout << "[" << it->getTypeName() << "] " << j << "$EIM$";
}
}
fflush(stderr);
fflush(stdout);
juce::shutdownJuce_GUI();
return 0;
}
auto deviceType = args->getValueForOption("-T|--type");
Expand All @@ -84,7 +89,8 @@ int main(int argc, char* argv[]) {
juce::AudioDeviceManager::AudioDeviceSetup setup;
setup.bufferSize = args->containsOption("-B|--bufferSize") ? args->getValueForOption("-B|--bufferSize").getIntValue() : 1024;
setup.sampleRate = args->containsOption("-R|--sampleRate") ? args->getValueForOption("-R|--sampleRate").getIntValue() : 48000;


eim::streams::output_stream::preventStdout();
eim::streams::out.writeByteOrderMessage();

if (deviceName == "#") deviceName = eim::streams::in.readString();
Expand All @@ -97,7 +103,6 @@ int main(int argc, char* argv[]) {
}
if (deviceType.isNotEmpty()) deviceManager.setCurrentAudioDeviceType(deviceType, true);
if (deviceName.isNotEmpty() && deviceName != "#") setup.outputDeviceName = deviceName;
juce::initialiseJuce_GUI();
auto error = deviceManager.initialise(0, 2, nullptr, true, "", &setup);
if (error.isNotEmpty()) {
eim::streams::out.writeError(error);
Expand All @@ -107,6 +112,9 @@ int main(int argc, char* argv[]) {

deviceManager.addAudioCallback(&audioCallback);

#if JUCE_MAC
juce::initialiseNSApplication();
#endif
juce::MessageManager::getInstance()->runDispatchLoop();
deviceManager.closeAudioDevice();
juce::shutdownJuce_GUI();
Expand Down
6 changes: 3 additions & 3 deletions src/audio_output.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace eim {

void audioDeviceIOCallbackWithContext(const float* const*, int, float* const* outputChannelData, int, int, const juce::AudioIODeviceCallbackContext&) override {
streams::out.writeAction(0);
eim::streams::output_stream::flush();
eim::streams::out.flush();
juce::int8 id;
if (streams::in.read(id) != 1) {
exit();
Expand Down Expand Up @@ -73,7 +73,7 @@ namespace eim {
streams::out.writeVarInt(bufferSizes.size());
for (int it : bufferSizes) streams::out.writeVarInt(it);
streams::out << device->hasControlPanel();
eim::streams::output_stream::flush();
eim::streams::out.flush();
int outBufferSize;
streams::in >> outBufferSize;
if (setup.bufferSize != bufSize) setup.bufferSize = bufSize;
Expand All @@ -86,7 +86,7 @@ namespace eim {
}

void audioDeviceError(const juce::String& errorMessage) override {
std::cout << errorMessage << '\n';
std::cerr << errorMessage << '\n';
isErrorExit = true;
exit();
}
Expand Down
11 changes: 7 additions & 4 deletions src/plugin_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ namespace eim {

streams::out.writeAction(1);
if (!shm) for (int i = 0; i < numOutputChannels; i++) streams::out.writeArray(buffer.getReadPointer(i), bufferSize);
eim::streams::output_stream::flush();
eim::streams::out.flush();
break;
}
case 2: {
Expand Down Expand Up @@ -226,10 +226,13 @@ namespace eim {
if (!processor->hasEditor()) return;
auto component = processor->createEditorIfNeeded();
if (!component) return;
long long parentHandle = 0;
#ifdef JUCE_WINDOWS
parentHandle = args->containsOption("-H|--handle") ? args->getValueForOption("-H|--handle").getLargeIntValue() : 0;
#endif
window = std::make_unique<PluginWindow>("[EIMHost] " + processor->getName() + " (" +
processor->getPluginDescription().pluginFormatName + ")", component, window,
processor->wrapperType != juce::AudioProcessor::wrapperType_VST,
args->containsOption("-H|--handle") ? args->getValueForOption("-H|--handle").getLargeIntValue() : 0);
processor->wrapperType != juce::AudioProcessor::wrapperType_VST, parentHandle);
}

void loadState(const juce::String& file) {
Expand All @@ -255,7 +258,7 @@ namespace eim {
streams::out << flags << p->getDefaultValue() << (int)p->getCategory()
<< p->getName(1024) << p->getLabel() << p->getAllValueStrings();
}
eim::streams::output_stream::flush();
eim::streams::out.flush();
}

void writeAllParameterChanges() {
Expand Down
32 changes: 17 additions & 15 deletions src/plugin_window.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,32 @@
#include <Windows.h>
#endif

int _width = 0, _height = 0, _x = 0, _y = 0;
int width_ = 0, height_ = 0, x_ = 0, y_ = 0;

class PluginWindow : public juce::ResizableWindow {
public:
PluginWindow(juce::String title, juce::Component* component, std::unique_ptr<PluginWindow>& ptr,
PluginWindow(const juce::String& title, juce::Component* component, std::unique_ptr<PluginWindow>& ptr,
bool resizable, long long parentHandle)
: ResizableWindow(title, !parentHandle), thisWindow(ptr) {
setUsingNativeTitleBar(true);
if (resizable) setResizable(true, false);

if (_width == 0) _width = component->getWidth();
if (_height == 0) _height = component->getHeight();
if (width_ == 0) width_ = component->getWidth();
if (height_ == 0) height_ = component->getHeight();

auto screenBounds = juce::Desktop::getInstance().getDisplays().getTotalBounds(true).toFloat();
auto scaleFactor = juce::jmin((screenBounds.getWidth() - 50) / getWidth(), (screenBounds.getHeight() - 50) / getHeight());
auto trueWidth = scaleFactor < 1.0f ? (int)(_width * scaleFactor) : _width;
auto trueHeight = scaleFactor < 1.0f ? (int)(_height * scaleFactor) : _height;
if (_x > 20 && _y > 20) setBounds(_x, _y, trueWidth, trueHeight); else centreWithSize(trueWidth, trueHeight);
auto scaleFactor = juce::jmin((screenBounds.getWidth() - 50) / (float)getWidth(), (screenBounds.getHeight() - 50) / (float)getHeight());
auto trueWidth = scaleFactor < 1.0f ? (int)((float)width_ * scaleFactor) : width_;
auto trueHeight = scaleFactor < 1.0f ? (int)((float)height_ * scaleFactor) : height_;
if (x_ > 20 && y_ > 20) setBounds(x_, y_, trueWidth, trueHeight); else centreWithSize(trueWidth, trueHeight);

setContentOwned(component, true);
setVisible(true);
PluginWindow::setVisible(true);

#ifdef JUCE_WINDOWS
if (parentHandle) addToDesktop(getDesktopWindowStyleFlags(), (HWND)(LONG_PTR)parentHandle);
#else
setAlwaysOnTop(true);
#endif
}

Expand All @@ -36,19 +38,19 @@ class PluginWindow : public juce::ResizableWindow {

void moved() override {
juce::ResizableWindow::moved();
_x = getX();
_y = getY();
x_ = getX();
y_ = getY();
}

void resized() override {
juce::ResizableWindow::resized();
_width = getWidth();
_height = getHeight();
width_ = getWidth();
height_ = getHeight();
}

void userTriedToCloseWindow() override { thisWindow.reset(nullptr); }

int getDesktopWindowStyleFlags() const override {
[[nodiscard]] int getDesktopWindowStyleFlags() const override {
return ResizableWindow::getDesktopWindowStyleFlags()
| juce::ComponentPeer::windowHasMinimiseButton
| (isResizable() ? juce::ComponentPeer::windowHasMaximiseButton : 0)
Expand All @@ -59,7 +61,7 @@ class PluginWindow : public juce::ResizableWindow {
private:
std::unique_ptr<PluginWindow>& thisWindow;

float getDesktopScaleFactor() const override { return 1.0f; }
[[nodiscard]] float getDesktopScaleFactor() const override { return 1.0f; }

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginWindow)
};
21 changes: 13 additions & 8 deletions src/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ namespace eim {
class output_stream {
public:
output_stream() {
setvbuf(stderr, nullptr, _IOFBF, 4096);
freopen(nullptr, "wb", stderr);
setvbuf(oldStdout, nullptr, _IOFBF, 4096);
freopen(nullptr, "wb", oldStdout);
#ifdef _WIN32
_setmode(_fileno(stderr), _O_BINARY);
_setmode(_fileno(oldStdout), _O_BINARY);
#endif
}

void write(bool var) { write((char)var); }
template <typename T> void write(T var) { std::fwrite(&var, sizeof(T), 1, stderr); }
template <typename T> void write(T var) { std::fwrite(&var, sizeof(T), 1, oldStdout); }
void write(const juce::Array<juce::String>& var) {
writeVarInt(var.size());
for (auto& str : var) write(str);
Expand All @@ -35,7 +35,7 @@ namespace eim {
writeVarInt(var.size());
for (auto& str : var) write(str);
}
template <typename T> void writeArray(T* var, int len) { std::fwrite(var, sizeof(T), (size_t) len, stderr); }
template <typename T> void writeArray(T* var, int len) { std::fwrite(var, sizeof(T), (size_t) len, oldStdout); }
template <typename T> output_stream& operator<<(T var) { write(var); return *this; }
output_stream& operator<<(bool var) { write(var); return *this; }
output_stream& operator<<(const juce::String& var) { write(var); return *this; }
Expand Down Expand Up @@ -65,7 +65,7 @@ namespace eim {
auto raw = str.toRawUTF8();
auto len = (int)strlen(raw);
writeVarInt(len);
std::fwrite(raw, sizeof(char), (size_t) len, stderr);
std::fwrite(raw, sizeof(char), (size_t) len, oldStdout);
}
void writeAction(juce::int8 action) { write(action); }
void writeByteOrderMessage() {
Expand All @@ -76,10 +76,15 @@ namespace eim {
write((char)127);
write(str);
flush();
std::cout << str << '\n';
std::cerr << str << '\n';
}

static void flush() { std::fflush(stderr); }
void flush() { std::fflush(oldStdout); }

static void preventStdout() { freopen("/dev/null", "w", stdout); }

private:
FILE *oldStdout = fdopen(dup(1), "wb");
};

class input_stream {
Expand Down

0 comments on commit b2ad233

Please sign in to comment.