/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /*************************************************************************** * pluginlv2test.cc * * Mon Feb 8 07:21:09 CET 2016 * Copyright 2016 Bent Bisballe Nyeng * deva@aasimon.org ****************************************************************************/ /* * This file is part of PluginGizmo. * * PluginGizmo is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * PluginGizmo 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with PluginGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #include "plugintest.h" #include "midievent.h" #include #include #include #include #include #ifdef LV2 // Entry point for lv2 plugin instantiation. PG_EXPORT PluginLV2* createEffectInstance() { return new PluginTest(); } #endif #ifdef VST // Entry point for vst plugin instantiation. PG_EXPORT AudioEffect* createEffectInstance(audioMasterCallback audioMaster) { return new PluginTest(audioMaster); } PluginTest::PluginTest(audioMasterCallback audioMaster) : PluginVST(audioMaster) { init(); } #endif void PluginTest::onFreeWheelChange(bool freewheel) { } void PluginTest::onSamplerateChange(float samplerate) { } void PluginTest::onFramesizeChange(size_t framesize) { } void PluginTest::onActiveChange(bool active) { } std::string PluginTest::onStateSave() { return ""; } void PluginTest::onStateRestore(const std::string& config) { } size_t PluginTest::getNumberOfMidiInputs() { return 1; } size_t PluginTest::getNumberOfMidiOutputs() { return 1; } size_t PluginTest::getNumberOfAudioInputs() { return 2; } size_t PluginTest::getNumberOfAudioOutputs() { return 2; } std::string PluginTest::getId() { return "PluginTest"; } std::string PluginTest::getEffectName() { return "Test plugin"; } std::string PluginTest::getURI() { return "http://example.com/plugintest"; } std::string PluginTest::getVendorString() { return "Test vendor"; } std::string PluginTest::getProductString() { return "Test product"; } std::string PluginTest::getHomepage() { return "https://www.example.com/pluginwebsite"; } PluginCategory PluginTest::getPluginCategory() { return PluginCategory::Synth; } void PluginTest::process(size_t pos, const std::vector& input_events, std::vector& output_events, const std::vector& input_samples, const std::vector& output_samples, size_t count) { setLatency(44100); float sample_rate = getSamplerate(); static float frequency = 0.0f; static float amplitude = 0.0f; for(auto& event : input_events) { if(event.type == MidiEventType::NoteOn) { float note = event.key; frequency = 110.0f * pow(2, note/12.0); amplitude = (float)event.velocity / 127.0f; } if(event.type == MidiEventType::NoteOff) { frequency = 0.0f; amplitude = 0.0f; } } for(float* ch : output_samples) { float p = pos; for(size_t s = 0; s < count; ++s) { const float pi = 3.141592653f; float value = sin(p * 2.0f * pi / sample_rate * frequency) * amplitude; //value = value * 10.0; ch[s] = value; p += 1.0f; } } } bool PluginTest::hasInlineGUI() { return true; } void PluginTest::onInlineRedraw(std::size_t width, std::size_t max_height, InlineDrawContext& context) { std::size_t height = std::min(width, max_height); if (!context.data || (context.width != width)) { context.width = width; context.height = height; context.data = (unsigned char*)inlineDisplayBuffer; } std::cout << "width: " << width << " height: " << height << std::endl; for(std::size_t x = 0; x < context.width; ++x) { for(std::size_t y = 0; y < context.height; ++y) { inlineDisplayBuffer[x + y * context.width] = pgzRGBA(lround(255 * (float(x) / float(context.width))), lround(255 * (1 + -1 * (float(x) / float(context.width)))), lround(255 * (float(y) / float(context.height))), 0); // Apparently not used } } } bool PluginTest::hasGUI() { return true; } static int n = 0; static const char message[] = "Hello, world!"; #if defined(WIN32) LRESULT CALLBACK PluginTest::wndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { auto self = (PluginTest*)GetWindowLongPtr(hwnd, GWLP_USERDATA); PAINTSTRUCT ps; HDC hdc; // Switch according to what type of message we have received switch(iMsg) { case WM_PAINT: // We receive WM_PAINT every time window is updated hdc = BeginPaint(hwnd, &ps); TextOut(hdc, 10, n % 100, message, 13); ++n; Rectangle(hdc, self->mouseX, self->mouseY, self->mouseX + 10, self->mouseY + 10); EndPaint(hwnd, &ps); break; case WM_MOUSEMOVE: self->mouseX = (short)LOWORD(lParam); self->mouseY = (short)HIWORD(lParam); break; } // Send any messages we don't handle to default window procedure return DefWindowProc(hwnd, iMsg, wParam, lParam); } #endif // defined(WIN32) void* PluginTest::createWindow(void *parent) { void* window = nullptr; #if defined(X11) xDisplay = XOpenDisplay(nullptr); xScreen = DefaultScreen(xDisplay); xWindow = XCreateSimpleWindow(xDisplay, (Window)parent, 10, 10, 100, 100, 1, BlackPixel(xDisplay, xScreen), WhitePixel(xDisplay, xScreen)); XSelectInput(xDisplay, xWindow, ExposureMask | KeyPressMask | PointerMotionMask); window = (void*)xWindow; #endif // defined(X11) #if defined(WIN32) static char szAppName[] = "PluginTest"; WNDCLASSEX wndclass = {}; hInstance = GetModuleHandle(nullptr); wndclass.cbSize = sizeof(wndclass); wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = PluginTest::wndProc; wndclass.hInstance = hInstance; wndclass.hCursor = LoadCursor(nullptr, IDC_ARROW); wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndclass.lpszClassName = szAppName; wndclass.lpszMenuName = NULL; wndclass.cbWndExtra = sizeof(PluginTest*); // Size of data. // Register a new window class with Windows RegisterClassEx(&wndclass); HWND hWndParent = (HWND)parent; // Create a window based on our new class hwnd = CreateWindow(szAppName, "PluginTest", ((parent ? WS_CHILD : WS_OVERLAPPEDWINDOW) | WS_VISIBLE ), 10, 10, 100, 100, hWndParent, NULL, hInstance, NULL); SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)this); window = (void*)hwnd; #endif // defined(WIN32) resizeWindow(100, 100); onShowWindow(); return window; } void PluginTest::onDestroyWindow() { #if defined(X11) XDestroyWindow(xDisplay, xWindow); XCloseDisplay(xDisplay); #endif // defined(X11) #if defined(WIN32) DestroyWindow(hwnd); // UnregisterClass(m_className, hInstance); #endif // defined(WIN32) } void PluginTest::onShowWindow() { #if defined(X11) XMapWindow(xDisplay, xWindow); #endif // defined(X11) #if defined(WIN32) // Show and update our window ShowWindow(hwnd, SW_SHOW); UpdateWindow(hwnd); #endif // defined(WIN32) } void PluginTest::onHideWindow() { #if defined(X11) XUnmapWindow(xDisplay, xWindow); #endif // defined(X11) #if defined(WIN32) ShowWindow(hwnd, SW_HIDE); #endif // defined(WIN32) } void PluginTest::onIdle() { #if defined(X11) XEvent xEvent; while(XPending(xDisplay) > 0) { XNextEvent(xDisplay, &xEvent); switch(xEvent.type) { case Expose: break; case MotionNotify: mouseX = xEvent.xmotion.x; mouseY = xEvent.xmotion.y; break; default: break; } } XClearWindow(xDisplay, xWindow); XDrawRectangle(xDisplay, xWindow, DefaultGC(xDisplay, xScreen), mouseX, mouseY, 10, 10); XDrawString(xDisplay, xWindow, DefaultGC(xDisplay, xScreen), 10, n % 100, message, strlen(message)); #endif // defined(X11) #if defined(WIN32) MSG msg; while(PeekMessage(&msg, hwnd, 0, 0, PM_NOREMOVE)) { GetMessage(&msg, hwnd, 0, 0); TranslateMessage(&msg); // for certain keyboard messages DispatchMessage(&msg); // send message to WndProc } InvalidateRect(hwnd, 0, TRUE); #endif // defined(WIN32) ++n; } void PluginTest::resizeWindow(size_t width, size_t height) { } void PluginTest::closeWindow() { }