Browse Source

Add ProjectM native plugin

tags/1.9.4
falkTX 11 years ago
parent
commit
ee6cdd9429
5 changed files with 463 additions and 1 deletions
  1. +5
    -0
      source/Makefile.mk
  2. +1
    -1
      source/modules/dgl/StandaloneWindow.hpp
  3. +23
    -0
      source/modules/native-plugins/Makefile
  4. +10
    -0
      source/modules/native-plugins/_all.c
  5. +424
    -0
      source/modules/native-plugins/projectm.cpp

+ 5
- 0
source/Makefile.mk View File

@@ -210,6 +210,7 @@ endif

HAVE_AF_DEPS = $(shell pkg-config --exists sndfile && echo true)
HAVE_MF_DEPS = $(shell pkg-config --exists smf && echo true)
HAVE_PM_DEPS = $(shell pkg-config --exists libprojectM && echo true)
HAVE_ZYN_DEPS = $(shell pkg-config --exists fftw3 mxml zlib && echo true)
HAVE_ZYN_UI_DEPS = $(shell pkg-config --exists ntk_images ntk && echo true)

@@ -389,6 +390,10 @@ ifeq ($(HAVE_MF_DEPS),true)
NATIVE_PLUGINS_LIBS += $(shell pkg-config --libs smf)
endif

ifeq ($(HAVE_PM_DEPS),true)
NATIVE_PLUGINS_LIBS += $(shell pkg-config --libs libprojectM)
endif

ifeq ($(HAVE_ZYN_DEPS),true)
NATIVE_PLUGINS_LIBS += $(shell pkg-config --libs fftw3 mxml zlib)
ifeq ($(HAVE_ZYN_UI_DEPS),true)


+ 1
- 1
source/modules/dgl/StandaloneWindow.hpp View File

@@ -67,7 +67,7 @@ public:
fWindow.setTitle(title);
}

private:
protected:
App fApp;
Window fWindow;
};


+ 23
- 0
source/modules/native-plugins/Makefile View File

@@ -26,6 +26,11 @@ ifeq ($(HAVE_MF_DEPS),true)
ALL_C_FLAGS += -DWANT_MIDIFILE
endif

# ProjectM
ifeq ($(HAVE_PM_DEPS),true)
ALL_C_FLAGS += -DWANT_PROJECTM
endif

# ZynAddSubFX
ifeq ($(HAVE_ZYN_DEPS),true)
ALL_C_FLAGS += -DWANT_ZYNADDSUBFX
@@ -39,6 +44,14 @@ MF_CXX_FLAGS = $(BUILD_CXX_FLAGS)
MF_CXX_FLAGS += $(shell pkg-config --cflags smf)
endif

# --------------------------------------------------------------
# Flags for ProjectM

ifeq ($(HAVE_PM_DEPS),true)
PM_CXX_FLAGS = $(BUILD_CXX_FLAGS)
PM_CXX_FLAGS += $(shell pkg-config --cflags libprojectM)
endif

# --------------------------------------------------------------
# Flags for ZynAddSubFX

@@ -121,6 +134,13 @@ ifeq ($(HAVE_MF_DEPS),true)
OBJS += midi-file.cpp.o
endif

# --------------------------------------------------------------
# ProjectM

ifeq ($(HAVE_PM_DEPS),true)
OBJS += projectm.cpp.o
endif

# --------------------------------------------------------------
# ZynAddSubFX

@@ -255,6 +275,9 @@ midi-file.cpp.o: midi-file.cpp midi-base.hpp $(CXXDEPS)
midi-sequencer.cpp.o: midi-sequencer.cpp midi-base.hpp $(CXXDEPS)
$(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@

projectm.cpp.o: projectm.cpp $(CXXDEPS)
$(CXX) $< $(PM_CXX_FLAGS) -c -o $@

notes.cpp.o: notes.cpp $(CXXDEPS) ../CarlaNativeExtUI.hpp
$(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@



+ 10
- 0
source/modules/native-plugins/_all.c View File

@@ -64,6 +64,11 @@ extern void carla_register_native_plugin_audiofile();
extern void carla_register_native_plugin_midifile();
#endif

#ifdef WANT_PROJECTM
// ProjectM
extern void carla_register_native_plugin_projectm();
#endif

// SunVox File
extern void carla_register_native_plugin_sunvoxfile();

@@ -122,6 +127,11 @@ void carla_register_all_plugins()
carla_register_native_plugin_midifile();
#endif

#ifdef WANT_PROJECTM
// ProjectM
carla_register_native_plugin_projectm();
#endif

// SunVox File
//carla_register_native_plugin_sunvoxfile();



+ 424
- 0
source/modules/native-plugins/projectm.cpp View File

@@ -0,0 +1,424 @@
/*
* Carla Native Plugins
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
*
* 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.
*/

#include "CarlaNative.hpp"
#include "CarlaMutex.hpp"

#include "dgl/StandaloneWindow.hpp"
#include "dgl/Widget.hpp"

#include "libprojectM/projectM.hpp"

// -----------------------------------------------------------------------

static const projectM::Settings kSettings = {
/* meshX */ 32,
/* meshY */ 24,
/* fps */ 35,
/* textureSize */ 1024,
/* windowWidth */ 512,
/* windowHeight */ 512,
/* presetURL */ "/usr/share/projectM/presets",
/* titleFontURL */ "/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf",
/* menuFontURL */ "/usr/share/fonts/truetype/ttf-dejavu/DejaVuSansMono.ttf",
/* smoothPresetDuration */ 5,
/* presetDuration */ 30,
/* beatSensitivity */ 10.0f,
/* aspectCorrection */ true,
/* easterEgg */ 1.0f,
/* shuffleEnabled */ true,
/* softCutRatingsEnabled */ false
};

// -----------------------------------------------------------------------

class ProjectMWidget : public DGL::Widget
{
public:
ProjectMWidget(DGL::Window& parent)
: DGL::Widget(parent),
pm(nullptr)
{
}

~ProjectMWidget()
{
if (pm == nullptr)
return;

delete pm;
pm = nullptr;
}

projectM* getPM() noexcept
{
return pm;
}

protected:
void onDisplay() override
{
if (pm == nullptr)
return;

pm->renderFrame();
}

void onClose() override
{
}

bool onKeyboard(const bool press, const uint32_t key) override
{
if (pm == nullptr)
return false;

projectMKeycode pmKey = PROJECTM_K_NONE;
projectMModifier pmMod = PROJECTM_KMOD_LSHIFT;

if ((key >= PROJECTM_K_0 && key <= PROJECTM_K_9) ||
(key >= PROJECTM_K_A && key <= PROJECTM_K_Z) ||
(key >= PROJECTM_K_a && key <= PROJECTM_K_z))
{
pmKey = static_cast<projectMKeycode>(key);
}
else
{
switch (key)
{
case DGL::CHAR_BACKSPACE:
pmKey = PROJECTM_K_BACKSPACE;
break;
case DGL::CHAR_ESCAPE:
pmKey = PROJECTM_K_ESCAPE;
break;
case DGL::CHAR_DELETE:
pmKey = PROJECTM_K_DELETE;
break;
}
}

if (pmKey == PROJECTM_K_NONE)
return false;

if (const int mod = getModifiers())
{
if (mod & DGL::MODIFIER_CTRL)
pmMod = PROJECTM_KMOD_LCTRL;
}

pm->key_handler(press ? PROJECTM_KEYUP : PROJECTM_KEYDOWN, pmKey, pmMod);

return true;
}

bool onSpecial(const bool press, const DGL::Key key) override
{
if (pm == nullptr)
return false;

projectMKeycode pmKey = PROJECTM_K_NONE;
projectMModifier pmMod = PROJECTM_KMOD_LSHIFT;

switch (key)
{
case DGL::KEY_F1:
pmKey = PROJECTM_K_F1;
break;
case DGL::KEY_F2:
pmKey = PROJECTM_K_F2;
break;
case DGL::KEY_F3:
pmKey = PROJECTM_K_F3;
break;
case DGL::KEY_F4:
pmKey = PROJECTM_K_F4;
break;
case DGL::KEY_F5:
pmKey = PROJECTM_K_F5;
break;
case DGL::KEY_F6:
pmKey = PROJECTM_K_F6;
break;
case DGL::KEY_F7:
pmKey = PROJECTM_K_F7;
break;
case DGL::KEY_F8:
pmKey = PROJECTM_K_F8;
break;
case DGL::KEY_F9:
pmKey = PROJECTM_K_F9;
break;
case DGL::KEY_F10:
pmKey = PROJECTM_K_F10;
break;
case DGL::KEY_F11:
pmKey = PROJECTM_K_F11;
break;
case DGL::KEY_F12:
pmKey = PROJECTM_K_F12;
break;
case DGL::KEY_LEFT:
pmKey = PROJECTM_K_LEFT;
break;
case DGL::KEY_UP:
pmKey = PROJECTM_K_UP;
break;
case DGL::KEY_RIGHT:
pmKey = PROJECTM_K_RIGHT;
break;
case DGL::KEY_DOWN:
pmKey = PROJECTM_K_DOWN;
break;
case DGL::KEY_PAGE_UP:
pmKey = PROJECTM_K_PAGEUP;
break;
case DGL::KEY_PAGE_DOWN:
pmKey = PROJECTM_K_PAGEDOWN;
break;
case DGL::KEY_HOME:
pmKey = PROJECTM_K_HOME;
break;
case DGL::KEY_END:
pmKey = PROJECTM_K_END;
break;
case DGL::KEY_INSERT:
pmKey = PROJECTM_K_INSERT;
break;
case DGL::KEY_SHIFT:
pmKey = PROJECTM_K_LSHIFT;
break;
case DGL::KEY_CTRL:
pmKey = PROJECTM_K_LCTRL;
break;
case DGL::KEY_ALT:
case DGL::KEY_SUPER:
break;
}

if (pmKey == PROJECTM_K_NONE)
return false;

if (const int mod = getModifiers())
{
if (mod & DGL::MODIFIER_CTRL)
pmMod = PROJECTM_KMOD_LCTRL;
}

pm->key_handler(press ? PROJECTM_KEYUP : PROJECTM_KEYDOWN, pmKey, pmMod);

return true;
}

void onReshape(const int width, const int height) override
{
/* Our shading model--Gouraud (smooth). */
glShadeModel(GL_SMOOTH);

/* Set the clear color. */
glClearColor(0, 0, 0, 0);
/* Setup our viewport. */
glViewport(0, 0, width, height);

/*
* Change to the projection matrix and set
* our viewing volume.
*/
glMatrixMode(GL_TEXTURE);
glLoadIdentity();

//gluOrtho2D(0.0, (GLfloat) width, 0.0, (GLfloat) height);
//glOrtho(0, width, height, 0, 0.0f, 1.0f);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glDrawBuffer(GL_BACK);
glReadBuffer(GL_BACK);
glEnable(GL_BLEND);

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_POINT_SMOOTH);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);

glLineStipple(2, 0xAAAA);

if (pm == nullptr)
pm = new projectM(kSettings); // std::string("/usr/share/projectM/config.inp"));

pm->projectM_resetGL(width, height);
}

private:
projectM* pm;

CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ProjectMWidget)
};

// -----------------------------------------------------------------------

class ProjectMUI : public DGL::StandaloneWindow
{
public:
ProjectMUI(const NativeHostDescriptor* const host)
: DGL::StandaloneWindow(),
fWidget(getWindow())
{
fWindow.setSize(kSettings.windowWidth, kSettings.windowHeight);
fWindow.setTitle(host->uiName);

if (host->uiParentId != 0)
fWindow.setTransientWinId(host->uiParentId);

fWindow.show();
}

projectM* getPM() noexcept
{
return fWidget.getPM();
}

void idle()
{
fApp.idle();
fWindow.repaint();
}

void focus()
{
fWindow.focus();
}

private:
ProjectMWidget fWidget;

CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ProjectMUI)
};

// -----------------------------------------------------------------------

class ProjectMPlugin : public NativePluginClass
{
public:
ProjectMPlugin(const NativeHostDescriptor* const host)
: NativePluginClass(host),
fPM(nullptr),
fUI(nullptr)
{
}

~ProjectMPlugin() override
{
CARLA_SAFE_ASSERT(fUI == nullptr);
}

protected:
// -------------------------------------------------------------------
// Plugin process calls

void process(float** ins, float**, const uint32_t frames, const NativeMidiEvent* const, const uint32_t) override
{
const CarlaMutexLocker csm(fMutex);

if (fPM == nullptr)
return;

fPM->pcm()->addPCMfloat(ins[0] ,frames);
}

// -------------------------------------------------------------------
// Plugin UI calls

void uiShow(const bool show) override
{
if (show)
{
if (fUI == nullptr)
fUI = new ProjectMUI(getHostHandle());

fUI->focus();
}
else if (fUI != nullptr)
{
{
const CarlaMutexLocker csm(fMutex);
fPM = nullptr;
}

delete fUI;
fUI = nullptr;
}
}

void uiIdle() override
{
if (fUI == nullptr)
return;

fUI->idle();

if (fPM != nullptr)
return;

const CarlaMutexLocker csm(fMutex);
fPM = fUI->getPM();
CARLA_SAFE_ASSERT(fPM != nullptr);
}

private:
projectM* fPM;
ProjectMUI* fUI;

// need to ensure pm is valid
CarlaMutex fMutex;

PluginClassEND(ProjectMPlugin)
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ProjectMPlugin)
};

// -----------------------------------------------------------------------

static const NativePluginDescriptor projectmDesc = {
/* category */ PLUGIN_CATEGORY_UTILITY,
/* hints */ static_cast<NativePluginHints>(/*PLUGIN_IS_RTSAFE|*/PLUGIN_HAS_UI|PLUGIN_USES_PARENT_ID),
/* supports */ static_cast<NativePluginSupports>(0x0),
/* audioIns */ 1,
/* audioOuts */ 0,
/* midiIns */ 0,
/* midiOuts */ 0,
/* paramIns */ 0,
/* paramOuts */ 0,
/* name */ "ProjectM",
/* label */ "projectm",
/* maker */ "falkTX",
/* copyright */ "GNU GPL v2+",
PluginDescriptorFILL(ProjectMPlugin)
};

// -----------------------------------------------------------------------

CARLA_EXPORT
void carla_register_native_plugin_projectm()
{
carla_register_native_plugin(&projectmDesc);
}

// -----------------------------------------------------------------------

Loading…
Cancel
Save