/* * Carla Native Plugins * Copyright (C) 2012-2015 Filipe Coelho * * 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 of * the License, or 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. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #ifndef CARLA_ZITA_COMMON_HPP_INCLUDED #define CARLA_ZITA_COMMON_HPP_INCLUDED #include "CarlaMutex.hpp" #include "CarlaThread.hpp" #include "LinkedList.hpp" #include #include #include #include #define EV_X11 16 #define EV_EXIT 31 // ----------------------------------------------------------------------- struct x_cairo_t { cairo_t * type; cairo_surface_t* surf; x_cairo_t() noexcept : type(nullptr), surf(nullptr) {} ~x_cairo_t() { cairo_destroy(type); cairo_surface_destroy(surf); } void initIfNeeded(X_display* const disp) { if (surf != nullptr) return; surf = cairo_xlib_surface_create(disp->dpy(), 0, disp->dvi(), 50, 50); type = cairo_create(surf); } }; // ----------------------------------------------------------------------- struct X_handler_Param { uint32_t index; float value; }; typedef LinkedList ParamList; template class X_handler_thread : public CarlaThread { public: struct SetValueCallback { virtual ~SetValueCallback() {} virtual void setParameterValueFromHandlerThread(const uint32_t index, const float value) = 0; }; X_handler_thread(SetValueCallback* const cb) : CarlaThread("X_handler"), fCallback(cb), fMutex(), fHandler(nullptr), fRootwin(nullptr), fMainwin(nullptr), fClosed(false), fParamMutex(), fParamChanges() {} void setupAndRun(X_handler* const h, X_rootwin* const r, MainwinType* const m) noexcept { const CarlaMutexLocker cml(fMutex); fHandler = h; fRootwin = r; fMainwin = m; startThread(); } void stopThread() noexcept { signalThreadShouldExit(); { const CarlaMutexLocker cml(fMutex); fHandler = nullptr; fRootwin = nullptr; fMainwin = nullptr; } CarlaThread::stopThread(1000); } CarlaMutex& getLock() noexcept { return fMutex; } void setParameterValueLater(const uint32_t index, const float value) noexcept { const CarlaMutexLocker cml(fParamMutex); for (ParamList::Itenerator it = fParamChanges.begin(); it.valid(); it.next()) { X_handler_Param& param(it.getValue()); if (param.index != index) continue; param.value = value; return; } const X_handler_Param param = { index, value }; fParamChanges.append(param); } bool wasClosed() noexcept { if (fClosed) { fClosed = false; return true; } return false; } private: SetValueCallback* const fCallback; CarlaMutex fMutex; X_handler* fHandler; X_rootwin* fRootwin; MainwinType* fMainwin; volatile bool fClosed; CarlaMutex fParamMutex; ParamList fParamChanges; void run() override { for (; ! shouldThreadExit();) { const CarlaMutexLocker cml(fMutex); CARLA_SAFE_ASSERT_RETURN(fMainwin != nullptr,); { const CarlaMutexLocker cml(fParamMutex); for (ParamList::Itenerator it = fParamChanges.begin(); it.valid(); it.next()) { const X_handler_Param& param(it.getValue()); fCallback->setParameterValueFromHandlerThread(param.index, param.value); } fParamChanges.clear(); } switch (fMainwin->process()) { case EV_X11: fRootwin->handle_event(); fHandler->next_event(); break; case EV_EXIT: fClosed = true; fHandler = nullptr; fMainwin = nullptr; fRootwin = nullptr; return; case Esync::EV_TIME: fRootwin->handle_event(); break; default: carla_stdout("custom X11 event for zita plugs"); break; } } } }; // ----------------------------------------------------------------------- #endif // CARLA_ZITA_COMMON_HPP_INCLUDED