Intercettare dati Midi grezzi con le funzioni esterne del API di RtMidi

Da Gambas-it.org - Wikipedia.

La libreria RtMidi è un insieme di classi, scritte in C++, che fornisce funzionalità per la gestione dei dati Midi in entrata ed in uscita.

E' possibile con alcune funzioni esterne della libreria RtMidi intercettare i dati Midi grezzi provenienti da un dispositivo Midi. Sarà necessario avere installata nel proprio sistema la libreria condivisa: librtmidi.so.7.0.0 ".

Mostriamo di seguito un possibile codice che intercetta i dati Midi grezzi provenienti da un dispositivo esterno e li scrive in console. Poiché la libreria RtMidi, come già accennato, è scritta in C++, non è possibile richiamare direttamente nel modo consueto con il comando Extern le sue necessarie funzioni esterne. Si rende, pertanto, necessario scrivere in C++ in un'apposita libreria condivisa, da noi realizzata, la parte di codice che richiama le predette funzioni esterne della libreria RtMidi, lasciando al codice dell'applicativo Gambas quanto più possibile e in particolare una funzione di coordinamento dell'intero processo. V'è da aggiungere che nell'esempio che segue, poiché non è stato possibile scrivere in autonome routine le varie funzioni esterne della libreria RtMidi, bensì tutte in quella sola principale, si è cercato un escamotage (come si potrà facilmente notare) per individuare e gestire da Gambas ogni singola funzione esterna necessaria.

Tale sorgente, da noi scritto in C++, della libreria dinamica condivisa esterna sarà posto nel codice dell'applicazione Gambas, dal quale anche si provvederà a creare la libreria medesima.

Il codice dell'applicativo Gambas (che tra l'altro prevede anche un Button posto sul Form) sarà dunque il seguente:

Library "/tmp/libadhoc"

' int main(int c, char** s)
' La funzione principale della libreria esterna da noi creata.
Private Extern main(c As Integer, s As Pointer) As Integer


Public Sub Form_Open()

  Dim p As Pointer
  Dim numPorteIn, numPorteEx As Integer
  Dim porta As String

  CreaSo()
   
  p = Alloc("PorteEntrata")
  numPorteIn = main(0, VarPtr(p))
  If numPorteIn = 0 Then Error.Raise("Impossibile trovare porte Midi in Entrata !")
  Free(p) 
 
  p = Alloc("NomePorteIn")
  main(0, VarPtr(p))
  
  TextArea1.Text = "Numero porte Midi di Entrata trovate: " & numPorteIn & Chr(10)
  TextArea1.Text &= String@(p)
  Free(p + 8)
   
  Me.Show

  porta = Val(InputBox("Porte Midi di Entrata trovate: " & numPorteIn & "\nScegli una porta:"))
 
  p = Alloc("openPort()")
  main(porta, VarPtr(p))
  Free(p)
  
  p = Alloc("ignoreTypes()")
  main(0, VarPtr(p))
  Free(p)

End


Public Sub Button1_Click()

 Me.Close
  
End


Private Procedure CreaSo()
 
 File.Save("/tmp/libadhoc.cpp", "#include <sstream>\n" &
         "#include <cstdlib>\n" &
         "#include \"RtMidi.h\"\n" &
         "#include <string.h>" &
         "\n\n" &
         "RtMidiIn * midiIn = 0;\n" &
         "unsigned int nPorteIn;\n" &
         "\n\n" &
         "void callback( double, std::vector< unsigned char > *, void * );" &
         "\n\n" &
         "int main(int c, char** s){" &
         "\n\n" &
         "  std::string nomePortaIn, a;\n" &
         "  std::stringstream n;\n" &
         "  unsigned int i;\n" &
         "\n\n" &
         "  midiIn = new RtMidiIn();\n" &
         "\n\n" &
         "  if (strcmp((char * )s[0], \"PorteEntrata\") == 0){\n"
         "    nPorteIn = midiIn->getPortCount();\n" &
         "    return nPorteIn;}" &
         "\n\n" &
         "  if (strcmp((char *)s[0], \"NomePorteIn\") == 0) {\n" &
         "    for ( i=0; i<nPorteIn; i++ ) {\n" &
         "      nomePortaIn = midiIn->getPortName(i);\n" &
         "      n << i;" &
         "/* Vengono unite le stringhe di tipo base */\n" &
         "      a = a + \" \" + n.str() + \" \" + nomePortaIn;\n" &
         "      n.str(" ");}" &
         "\n\n" &
         "/* La variabile base stringa \"a\" viene convertita nel tipo 'char*'\n" &
         "affinché possa essere restituita al codice Gambas attraverso\n" &
         "il parametro \"char** s\" della routine \"main()\" */\n" &
         "    char* ritornare = strcpy((char*)malloc(a.length()+1), a.c_str());\n" &
         "    *s =  ritornare;}" &
         "\n\n" &
         "  if (strcmp((char *)s[0], \"openPort()\") == 0) {\n" &
         "    midiIn->openPort( c );\n" &
         "    midiIn->setCallback( &callback );}" &
         "\n\n" &
         "/* Imposta i valori booleani, se deve ignorare rispettivamente i messaggi:\n" &
         "sysex, timing, active sensing*/\n" &
         "  if (strcmp((char *)s[0], \"ignoreTypes()\") == 0) {\n" &
         "    midiIn->ignoreTypes( false, true, true);\n}" &
         "\n\n" &
         "  return (0);\n}" &
         "\n\n" &
         "void callback( double tempodelta, std::vector< unsigned char > *messaggio, void */*userData*/ ) {" &
         "\n\n" &
         "  unsigned int nByte = messaggio->size();\n" &
         "  for ( unsigned int j=0; j<nByte; j++ )\n" &
         "    std::cout << \"Byte \" << j << \" = \" << (int)messaggio->at(j) << \", \";\n" &
         "  if ( nByte > 0 )\n" &
         "    std::cout << \"timestamp = \" << tempodelta << std::endl;\n}")
  
 Shell "g++ -o /tmp/libadhoc.so /tmp/libadhoc.cpp -shared -fPIC -lrtmidi" Wait
 
End



Riferimenti