aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--core/qmpmidiplay.cpp45
-rw-r--r--core/qmpmidiplay.hpp17
-rw-r--r--include/qmpcorepublic.hpp17
-rw-r--r--qmidiplayer-desktop/qmpchannelswindow.cpp2
-rw-r--r--qmidiplayer-desktop/qmpchannelswindow.hpp3
-rw-r--r--qmidiplayer-desktop/qmpinfowindow.cpp2
-rw-r--r--qmidiplayer-desktop/qmpmainwindow.cpp1
-rw-r--r--qmidiplayer-desktop/qmpplugin.cpp33
-rw-r--r--visualization/qmpvisualization.cpp45
-rw-r--r--visualization/qmpvisualization.hpp36
-rw-r--r--visualization/visualization.pro23
12 files changed, 213 insertions, 19 deletions
diff --git a/ChangeLog b/ChangeLog
index 1294fad..fdfc2f1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,12 @@
2016-04-23 0.7.8 alpha
+More implementation of plugin support.
+Migrate channel activity indicator to the new
+callback system.
+Added a testing plugin.
+Plugins are now loaded correctly.
+However the plugin API is not working properly.
+
+2016-04-23 0.7.8 alpha
Basic stubs for plugin support.
2016-04-22 0.7.2
diff --git a/core/qmpmidiplay.cpp b/core/qmpmidiplay.cpp
index cbed018..4e28be0 100644
--- a/core/qmpmidiplay.cpp
+++ b/core/qmpmidiplay.cpp
@@ -50,6 +50,8 @@ void CMidiPlayer::fluidDeinitialize()
void CMidiPlayer::processEvent(const SEvent *e)
{
SEventCallBackData cbd(e->type,e->p1,e->p2);
+ for(int i=0;i<16;++i)if(eventHandlerCB[i])
+ eventHandlerCB[i]->callBack(&cbd,eventHandlerCBuserdata[i]);
switch(e->type&0xF0)
{
case 0x80://Note off
@@ -61,7 +63,6 @@ void CMidiPlayer::processEvent(const SEvent *e)
case 0x90://Note on
if((mute>>(e->type&0x0F))&1)break;//muted
if(solo&&!((solo>>(e->type&0x0F))&1))break;
- if(noteOnCB)noteOnCB->callBack(&cbd,noteOnCBUserData);
if(mappedoutput[e->type&0x0F])
mapper->noteOn(mappedoutput[e->type&0x0F]-1,e->type&0x0F,e->p1,e->p2);
else
@@ -272,7 +273,10 @@ CMidiPlayer::CMidiPlayer(bool singleInst)
{
midiFile=NULL;resumed=false;singleInstance=singleInst;
settings=NULL;synth=NULL;adriver=NULL;waitvoice=true;
- noteOnCB=NULL;noteOnCBUserData=NULL;
+ memset(eventHandlerCB,0,sizeof(eventHandlerCB));
+ memset(eventHandlerCBuserdata,0,sizeof(eventHandlerCBuserdata));
+ memset(eventReaderCB,0,sizeof(eventReaderCB));
+ memset(eventReaderCBuserdata,0,sizeof(eventReaderCBuserdata));
memset(mappedoutput,0,sizeof(mappedoutput));
memset(deviceusage,0,sizeof(deviceusage));
mapper=new qmpMidiMapperRtMidi();
@@ -314,6 +318,8 @@ void CMidiPlayer::playerPanic(bool reset)
bool CMidiPlayer::playerLoadFile(const char* fn)
{
midiFile=new CMidiFile(fn);
+ memcpy(midiFile->eventReaderCB,this->eventReaderCB,sizeof(this->eventReaderCB));
+ memcpy(midiFile->eventReaderCBuserdata,this->eventReaderCBuserdata,sizeof(this->eventReaderCBuserdata));
if(!midiFile->isValid())return false;
divs=midiFile->getDivision();
fileTimer1Pass();
@@ -392,12 +398,13 @@ void CMidiPlayer::setTCeptr(uint32_t ep,uint32_t st)
}
double CMidiPlayer::getFtime(){return ftime;}
void CMidiPlayer::getCurrentTimeSignature(int *n,int *d){*n=ctsn;*d=ctsd;}
-void CMidiPlayer::getCurrentKeySignature(int *ks){*ks=cks;}
+int CMidiPlayer::getCurrentKeySignature(){return cks;}
uint32_t CMidiPlayer::getFileNoteCount(){return midiFile?midiFile->getNoteCount():0;}
uint32_t CMidiPlayer::getFileStandard(){return midiFile?midiFile->getStandard():0;}
const char* CMidiPlayer::getTitle(){return midiFile?midiFile->getTitle():"";}
const char* CMidiPlayer::getCopyright(){return midiFile?midiFile->getCopyright():"";}
double CMidiPlayer::getTempo(){return 60./(ctempo/1e6);}
+uint32_t CMidiPlayer::getRawTempo(){return ctempo;}
uint32_t CMidiPlayer::getDivision(){return divs;}
uint32_t CMidiPlayer::getTCpaused(){return tcpaused;}
void CMidiPlayer::setTCpaused(uint32_t ps){tcpaused=ps;}
@@ -530,5 +537,33 @@ void CMidiPlayer::setChannelOutput(int ch,int devid)
}else fluid_synth_all_notes_off(synth,ch);
}
uint8_t* CMidiPlayer::getChstates(){return chstate;}
-void CMidiPlayer::setNoteOnCallBack(IMidiCallBack *cb,void *userdata)
-{noteOnCB=cb;noteOnCBUserData=userdata;}
+int CMidiPlayer::setEventHandlerCB(IMidiCallBack *cb,void *userdata)
+{
+ for(int i=0;i<16;++i)
+ {
+ if(eventHandlerCB[i]==cb)return i;
+ if(eventHandlerCB[i]==NULL)
+ {
+ eventHandlerCB[i]=cb;eventHandlerCBuserdata[i]=userdata;
+ return i;
+ }
+ }
+ return -1;
+}
+void CMidiPlayer::unsetEventHandlerCB(int id)
+{eventHandlerCB[id]=NULL;eventHandlerCBuserdata[id]=NULL;}
+int CMidiPlayer::setEventReaderCB(IMidiCallBack *cb,void *userdata)
+{
+ for(int i=0;i<16;++i)
+ {
+ if(eventReaderCB[i]==cb)return i;
+ if(eventReaderCB[i]==NULL)
+ {
+ eventReaderCB[i]=cb;eventReaderCBuserdata[i]=userdata;
+ return i;
+ }
+ }
+ return -1;
+}
+void CMidiPlayer::unsetEventReaderCB(int id)
+{eventReaderCB[id]=NULL;eventReaderCBuserdata[id]=NULL;}
diff --git a/core/qmpmidiplay.hpp b/core/qmpmidiplay.hpp
index 4f3b50f..35fecea 100644
--- a/core/qmpmidiplay.hpp
+++ b/core/qmpmidiplay.hpp
@@ -23,6 +23,7 @@ struct SEvent
};
class CMidiFile
{
+ friend class CMidiPlayer;
private:
std::vector<SEvent*>eventList;
char *title,*copyright;
@@ -31,6 +32,8 @@ class CMidiFile
FILE *f;
int byteread,valid;
uint32_t notes,curt,curid;
+ IMidiCallBack* eventReaderCB[16];
+ void* eventReaderCBuserdata[16];
void error(int fatal,const char* format,...);
uint32_t readSW();
@@ -76,8 +79,10 @@ class CMidiPlayer
qmpMidiMapperRtMidi *mapper;
int mappedoutput[16],deviceusage[16],deviceiid[128];
uint8_t chstate[16],chstatus[16][130];//0..127: cc 128: pc
- IMidiCallBack *noteOnCB;
- void* noteOnCBUserData;
+ IMidiCallBack* eventHandlerCB[16];
+ IMidiCallBack* eventReaderCB[16];
+ void* eventHandlerCBuserdata[16];
+ void* eventReaderCBuserdata[16];
void setBit(uint16_t &n,uint16_t bn,uint16_t b);
void processEvent(const SEvent *e);
@@ -115,10 +120,11 @@ class CMidiPlayer
double getFtime();
void getCurrentTimeSignature(int *n,int *d);
- void getCurrentKeySignature(int *ks);
+ int getCurrentKeySignature();
uint32_t getFileNoteCount();
uint32_t getFileStandard();
double getTempo();
+ uint32_t getRawTempo();
uint32_t getDivision();
const char* getTitle();
const char* getCopyright();
@@ -148,6 +154,9 @@ class CMidiPlayer
qmpMidiMapperRtMidi* getMidiMapper();
void setChannelOutput(int ch,int devid);
uint8_t* getChstates();
- void setNoteOnCallBack(IMidiCallBack *cb,void *userdata);
+ int setEventHandlerCB(IMidiCallBack *cb,void *userdata);
+ void unsetEventHandlerCB(int id);
+ int setEventReaderCB(IMidiCallBack *cb,void *userdata);
+ void unsetEventReaderCB(int id);
};
#endif
diff --git a/include/qmpcorepublic.hpp b/include/qmpcorepublic.hpp
index 7348beb..ad6a165 100644
--- a/include/qmpcorepublic.hpp
+++ b/include/qmpcorepublic.hpp
@@ -17,10 +17,11 @@ class IMidiCallBack
class qmpPluginIntf
{
public:
- virtual void init();
- virtual void deinit();
- virtual const char* pluginGetName();
- virtual const char* pluginGetVersion();
+ virtual ~qmpPluginIntf(){}
+ virtual void init(){}
+ virtual void deinit(){}
+ virtual const char* pluginGetName(){return "";}
+ virtual const char* pluginGetVersion(){return "";}
};
class qmpVisualizationIntf
{
@@ -28,6 +29,7 @@ class qmpVisualizationIntf
virtual void show();
virtual void close();
};
+extern "C"{
class qmpPluginAPI
{
public:
@@ -35,15 +37,15 @@ class qmpPluginAPI
uint32_t getRawTempo();
double getRealTempo();
uint32_t getTimeSig();
- uint32_t getKeySig();
+ int getKeySig();
uint32_t getNoteCount();
uint32_t getCurrentPolyphone();
uint32_t getMaxPolyphone();
uint32_t getCurrentTimeStamp();
int registerVisualizationIntf(qmpVisualizationIntf* i);
void unregisterVisualizationIntf(int intfhandle);
- int registerEventReadHandlerIntf(IMidiCallBack* cb,void* userdata);
- void unregisterEventReadHandlerIntf(IMidiCallBack* cb,void* userdata);
+ int registerEventReaderIntf(IMidiCallBack* cb,void* userdata);
+ void unregisterEventReaderIntf(int intfhandle);
int registerEventHandlerIntf(IMidiCallBack* cb,void* userdata);
void unregisterEventHandlerIntf(int intfhandle);
void registerOptionInt(std::string desc,std::string key,int defaultval);
@@ -53,5 +55,6 @@ class qmpPluginAPI
void registerOptionString(std::string desc,std::string key,std::string defaultval);
std::string getOptionString(std::string key);
};
+}
typedef qmpPluginIntf*(*qmpPluginEntry)(qmpPluginAPI*);
#endif // QMPCOREPUBLIC_H
diff --git a/qmidiplayer-desktop/qmpchannelswindow.cpp b/qmidiplayer-desktop/qmpchannelswindow.cpp
index 282a4cc..7def34d 100644
--- a/qmidiplayer-desktop/qmpchannelswindow.cpp
+++ b/qmidiplayer-desktop/qmpchannelswindow.cpp
@@ -17,7 +17,7 @@ qmpChannelsWindow::qmpChannelsWindow(QWidget *parent) :
mapper=qmpMainWindow::getInstance()->getPlayer()->getMidiMapper();
cha=new QPixmap(":/img/ledon.png");chi=new QPixmap(":/img/ledoff.png");
cb=new qmpCWNoteOnCB();fused=callbacksc=cbcnt=0;
- qmpMainWindow::getInstance()->getPlayer()->setNoteOnCallBack(cb,NULL);
+ qmpMainWindow::getInstance()->getPlayer()->setEventHandlerCB(cb,NULL);
connect(cb,SIGNAL(onNoteOn()),this,SLOT(updateChannelActivity()));
int devc=mapper->enumDevices();
//We setup default output here...
diff --git a/qmidiplayer-desktop/qmpchannelswindow.hpp b/qmidiplayer-desktop/qmpchannelswindow.hpp
index 15a53d6..0fa1e06 100644
--- a/qmidiplayer-desktop/qmpchannelswindow.hpp
+++ b/qmidiplayer-desktop/qmpchannelswindow.hpp
@@ -63,7 +63,8 @@ class qmpCWNoteOnCB:public QObject,public IMidiCallBack
{
Q_OBJECT
public:
- void callBack(void*,void*){emit onNoteOn();}
+ void callBack(void* callerdata,void*)
+ {if(((((SEventCallBackData*)callerdata)->type)&0xF0)==0x90)emit onNoteOn();}
signals:
void onNoteOn();
};
diff --git a/qmidiplayer-desktop/qmpinfowindow.cpp b/qmidiplayer-desktop/qmpinfowindow.cpp
index 689a756..95ad223 100644
--- a/qmidiplayer-desktop/qmpinfowindow.cpp
+++ b/qmidiplayer-desktop/qmpinfowindow.cpp
@@ -45,7 +45,7 @@ void qmpInfoWindow::updateInfo()
}
else ui->lbCopyright->setText(QString("Copyright: "));
ui->lbTempo->setText(QString("Tempo: ")+QString::number(player->getTempo(),'g',5));
- int t,r;player->getCurrentKeySignature(&t);r=(int8_t)((t>>8)&0xFF)+7;
+ int t,r;t=player->getCurrentKeySignature();r=(int8_t)((t>>8)&0xFF)+7;
strncpy(str,t&0xFF?minors+2*r:majors+2*r,2);str[2]='\0';
ui->lbKeySig->setText(QString("Key Sig.: ")+str);
player->getCurrentTimeSignature(&t,&r);sprintf(str,"Time Sig.: %d/%d",t,r);
diff --git a/qmidiplayer-desktop/qmpmainwindow.cpp b/qmidiplayer-desktop/qmpmainwindow.cpp
index 84697a4..9d73626 100644
--- a/qmidiplayer-desktop/qmpmainwindow.cpp
+++ b/qmidiplayer-desktop/qmpmainwindow.cpp
@@ -75,6 +75,7 @@ void qmpMainWindow::init()
ui->lbFileName->addAction(fnA1);
ui->lbFileName->addAction(fnA2);
ui->lbFileName->addAction(fnA3);
+ pmgr->scanPlugins();pmgr->initPlugins();
if(singleFS){player->fluidPreInitialize();playerSetup();player->fluidInitialize();
for(int i=settingsw->getSFWidget()->count()-1;i>=0;--i)
LOAD_SOUNDFONT;}
diff --git a/qmidiplayer-desktop/qmpplugin.cpp b/qmidiplayer-desktop/qmpplugin.cpp
index 4da1698..559b575 100644
--- a/qmidiplayer-desktop/qmpplugin.cpp
+++ b/qmidiplayer-desktop/qmpplugin.cpp
@@ -4,6 +4,7 @@
#include <dlfcn.h>
#include <dirent.h>
#endif
+#include <cstdio>
#include <cstring>
#include "qmpplugin.hpp"
#include "qmpmainwindow.hpp"
@@ -53,6 +54,38 @@ qmpPluginManager::~qmpPluginManager()
{
qmw=NULL;qsw=NULL;
}
+void qmpPluginManager::initPlugins()
+{
+ for(unsigned i=0;i<plugins.size();++i)
+ {
+ printf("Loaded plugin: %s\n",plugins[i].path.c_str());
+ plugins[i].interface->init();
+ }
+}
uint32_t qmpPluginAPI::getDivision()
{return qmw->getPlayer()->getDivision();}
+uint32_t qmpPluginAPI::getRawTempo()
+{return qmw->getPlayer()->getRawTempo();}
+double qmpPluginAPI::getRealTempo()
+{return qmw->getPlayer()->getTempo();}
+uint32_t qmpPluginAPI::getTimeSig()
+{int n,d=0,t;qmw->getPlayer()->getCurrentTimeSignature(&n,&t);for(;t>>=1;++d);return n<<8|d;}
+int qmpPluginAPI::getKeySig()
+{return qmw->getPlayer()->getCurrentKeySignature();}
+uint32_t qmpPluginAPI::getNoteCount()
+{return qmw->getPlayer()->getFileNoteCount();}
+uint32_t qmpPluginAPI::getCurrentPolyphone()
+{return qmw->getPlayer()->getPolyphone();}
+uint32_t qmpPluginAPI::getMaxPolyphone()
+{return qmw->getPlayer()->getMaxPolyphone();}
+uint32_t qmpPluginAPI::getCurrentTimeStamp()
+{return qmw->getPlayer()->getTCeptr();}
+int qmpPluginAPI::registerEventHandlerIntf(IMidiCallBack *cb,void *userdata)
+{return qmw->getPlayer()->setEventHandlerCB(cb,userdata);}
+void qmpPluginAPI::unregisterEventHandlerIntf(int intfhandle)
+{qmw->getPlayer()->unsetEventHandlerCB(intfhandle);}
+int qmpPluginAPI::registerEventReaderIntf(IMidiCallBack *cb,void *userdata)
+{return qmw->getPlayer()->setEventReaderCB(cb,userdata);}
+void qmpPluginAPI::unregisterEventReaderIntf(int intfhandle)
+{qmw->getPlayer()->unsetEventReaderCB(intfhandle);}
diff --git a/visualization/qmpvisualization.cpp b/visualization/qmpvisualization.cpp
new file mode 100644
index 0000000..e8bb9fb
--- /dev/null
+++ b/visualization/qmpvisualization.cpp
@@ -0,0 +1,45 @@
+#include <cstdio>
+#include "qmpvisualization.hpp"
+
+void CTestCallBack::callBack(void *callerdata,void *)
+{
+ if(par->c<3)
+ {
+ SEventCallBackData* cbd=(SEventCallBackData*)callerdata;
+ printf("type %#x p1 %d p2 %d\n",cbd->type,cbd->p1,cbd->p2);
+ }
+}
+
+qmpVisualization::qmpVisualization(qmpPluginAPI* _api)
+{api=_api;}
+qmpVisualization::~qmpVisualization()
+{api=NULL;}
+void qmpVisualization::init()
+{
+ puts("hello world from test plugin!");
+ puts("I'll try to print the first 3 events from the file!");
+ cb=new CTestCallBack(this);c=0;
+ //!!FIXME: not working properly...
+ api->registerEventReaderIntf(cb,NULL);
+}
+void qmpVisualization::deinit()
+{}
+const char* qmpVisualization::pluginGetName()
+{return "QMidiPlayer Default Visualization Plugin";}
+const char* qmpVisualization::pluginGetVersion()
+{return "0.7.8";}
+
+//dummy implementations of the api...
+uint32_t qmpPluginAPI::getDivision(){return 0;}
+uint32_t qmpPluginAPI::getRawTempo(){return 0;}
+double qmpPluginAPI::getRealTempo(){return 0;}
+uint32_t qmpPluginAPI::getTimeSig(){return 0;}
+int qmpPluginAPI::getKeySig(){return 0;}
+uint32_t qmpPluginAPI::getNoteCount(){return 0;}
+uint32_t qmpPluginAPI::getCurrentPolyphone(){return 0;}
+uint32_t qmpPluginAPI::getMaxPolyphone(){return 0;}
+uint32_t qmpPluginAPI::getCurrentTimeStamp(){return 0;}
+int qmpPluginAPI::registerEventHandlerIntf(IMidiCallBack*,void*){return -1;}
+void qmpPluginAPI::unregisterEventHandlerIntf(int){}
+int qmpPluginAPI::registerEventReaderIntf(IMidiCallBack*,void*){return -1;}
+void qmpPluginAPI::unregisterEventReaderIntf(int){}
diff --git a/visualization/qmpvisualization.hpp b/visualization/qmpvisualization.hpp
new file mode 100644
index 0000000..847f37b
--- /dev/null
+++ b/visualization/qmpvisualization.hpp
@@ -0,0 +1,36 @@
+#ifndef QMPVISUALIZATION_H
+#define QMPVISUALIZATION_H
+
+#include "../include/qmpcorepublic.hpp"
+
+class qmpVisualization;
+class CTestCallBack:public IMidiCallBack
+{
+ private:
+ qmpVisualization *par;
+ public:
+ CTestCallBack(qmpVisualization *_par){par=_par;}
+ void callBack(void *callerdata,void *userdata);
+};
+class qmpVisualization:public qmpPluginIntf
+{
+ friend class CTestCallBack;
+ private:
+ qmpPluginAPI* api;
+ int c;
+ CTestCallBack* cb;
+ public:
+ qmpVisualization(qmpPluginAPI* _api);
+ ~qmpVisualization();
+ void init();
+ void deinit();
+ const char* pluginGetName();
+ const char* pluginGetVersion();
+};
+
+extern "C"{
+ qmpPluginIntf* qmpPluginGetInterface(qmpPluginAPI* api)
+ {return new qmpVisualization(api);}
+}
+
+#endif // QMPVISUALIZATION_H
diff --git a/visualization/visualization.pro b/visualization/visualization.pro
new file mode 100644
index 0000000..8cce718
--- /dev/null
+++ b/visualization/visualization.pro
@@ -0,0 +1,23 @@
+#-------------------------------------------------
+#
+# Project created by QtCreator 2016-04-24T22:04:32
+#
+#-------------------------------------------------
+
+QT -= core gui
+
+CONFIG += c++11
+
+TARGET = visualization
+TEMPLATE = lib
+
+DEFINES += VISUALIZATION_LIBRARY
+
+SOURCES += qmpvisualization.cpp
+
+HEADERS += qmpvisualization.hpp
+
+unix {
+ target.path = /usr/lib/qmidiplayer
+ INSTALLS += target
+}