Differenze tra le versioni di "Intercettare dati Midi grezzi con le funzioni esterne del API di RtMidi"

Da Gambas-it.org - Wikipedia.
 
(6 versioni intermedie di uno stesso utente non sono mostrate)
Riga 1: Riga 1:
La libreria ''RtMidi'' è un insieme di classi C++ che fornisce funzionalità per la gestione dei dati Midi in entrata ed in uscita.
+
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.1.2.0.1''
 
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.1.2.0.1''
  
 +
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.
  
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.
  
La libreria esterna, da noi scritta, il cui sorgente in linguaggio C++ chiameremo ad esempio ''libadhoc.cpp'' è la seguente:
+
Il codice dell'applicativo Gambas (che tra l'altro prevede anche un ''Button'' posto sul Form) sarà dunque il seguente:
  #include <sstream>
+
  Library "/tmp/libadhoc"
#include <cstdlib>
 
#include "RtMidi.h"
 
#include <string.h>
 
 
 
RtMidiIn *midiIn = 0;
 
unsigned int nPorteIn, nPorteEx;
 
 
void callback( double, std::vector< unsigned char > *, void * );
 
 
 
int main(int c, char** s) {
 
 
   
 
   
  std::string nomePortaIn, nomePortaOut, a;
+
<FONT Color=gray>' ''int main(int c, char** s)''
  std::stringstream n;
+
' ''La funzione principale della libreria esterna da noi creata.''</font>
  unsigned int i;
+
Private Extern main(c As Integer, s As Pointer) As Integer
 
   
 
   
  midiIn = new RtMidiIn();
 
 
   
 
   
  if (strcmp((char *)s[0], "PorteEntrata") == 0) {
+
Public Sub Form_Open()
    nPorteIn = midiIn->getPortCount();
 
    return nPorteIn;
 
  }
 
 
   
 
   
 +
  Dim p As Pointer
 +
  Dim numPorteIn, numPorteEx As Integer
 +
  Dim porta As String
 
   
 
   
   if (strcmp((char *)s[0], "NomePorteIn") == 0) {
+
   CreaSo()
    for ( i=0; i<nPorteIn; i++ ) {
 
      nomePortaIn = midiIn->getPortName(i);
 
      n << i;
 
/* Vengono unite le stringhe di tipo base */
 
      a = a + "\n" + n.str() + " " + nomePortaIn;
 
      n.str("");
 
    }
 
/* La variabile base stringa "a" viene convertita nel tipo 'char*'
 
    affinché possa essere restituita al codice Gambas attraverso il parametro "char** s" della routine "main()" */
 
      char* ritornare = strcpy((char*)malloc(a.length()+1), a.c_str());
 
      *s =  ritornare;
 
  }
 
 
 
 
 
  if (strcmp((char *)s[0], "openPort()") == 0) {
 
    midiIn->openPort( c );
 
    midiIn->setCallback( &callback );
 
  }
 
 
      
 
      
   
 
<FONT color=gray>/* Imposta i valori booleani, se deve ignorare rispettivamente i messaggi: '''sysex''', '''timing''', '''active sensing'''*/</font>
 
    if (strcmp((char *)s[0], "ignoreTypes()") == 0) {
 
      midiIn->ignoreTypes( false, true, true);
 
    }
 
 
 
  return (0);
 
 
 
}
 
 
 
void callback( double tempodelta, std::vector< unsigned char > *messaggio, void */*userData*/ ) {
 
  unsigned int nByte = messaggio->size();
 
  for ( unsigned int j=0; j<nByte; j++ )
 
    std::cout << "Byte " << j << " = " << (int)messaggio->at(j) << ", ";
 
  if ( nByte > 0 )
 
    std::cout << "timestamp = " << tempodelta << std::endl;
 
}
 
Tale sorgente, da noi scritto, della libreria condivisa sarà posto ad esempio nella cartella "''Dati''" dell'applicativo.
 
 
 
Il codice dell'applicativo Gambas, che tra l'altro prevede anche un ''Button'' posto sul Form, sarà invece il seguente:
 
'''Public''' Sub Form_Open()
 
 
  Dim numPorteIn, numPorteEx As Integer
 
  Dim p As Pointer
 
  Dim porta As String
 
 
  Shell "g++ -o /tmp/libadhoc.so " & Application.Path &/ "libadhoc.cpp -shared -fPIC -lrtmidi" Wait
 
 
 
   p = Alloc("PorteEntrata")
 
   p = Alloc("PorteEntrata")
 
   numPorteIn = main(0, VarPtr(p))
 
   numPorteIn = main(0, VarPtr(p))
 
   If numPorteIn = 0 Then Error.Raise("Impossibile trovare porte Midi in Entrata !")
 
   If numPorteIn = 0 Then Error.Raise("Impossibile trovare porte Midi in Entrata !")
+
  Free(p)
 
    
 
    
 
   p = Alloc("NomePorteIn")
 
   p = Alloc("NomePorteIn")
 
   main(0, VarPtr(p))
 
   main(0, VarPtr(p))
 
+
 
 
   TextArea1.Text = "Numero porte Midi di Entrata trovate: " & numPorteIn & Chr(10)
 
   TextArea1.Text = "Numero porte Midi di Entrata trovate: " & numPorteIn & Chr(10)
 
   TextArea1.Text &= String@(p)
 
   TextArea1.Text &= String@(p)
 +
  Free(p + 8)
 
      
 
      
 
   Me.Show
 
   Me.Show
Riga 101: Riga 41:
 
   p = Alloc("openPort()")
 
   p = Alloc("openPort()")
 
   main(porta, VarPtr(p))
 
   main(porta, VarPtr(p))
 +
  Free(p)
 
    
 
    
 
   p = Alloc("ignoreTypes()")
 
   p = Alloc("ignoreTypes()")
 
   main(0, VarPtr(p))
 
   main(0, VarPtr(p))
 +
  Free(p)
 +
 +
End
 
   
 
   
'''End'''
 
 
   
 
   
 +
Public Sub Button1_Click()
 
   
 
   
  '''Public''' Sub Button1_Click()
+
  Me.Close
 +
 
 +
  End
 
   
 
   
  Quit
 
 
   
 
   
  '''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
  
  
Riga 118: Riga 122:
  
 
=Riferimenti=
 
=Riferimenti=
* [http://www.music.mcgill.ca/~gary/rtmidi/ Il sito di RtMidi]
+
* http://www.music.mcgill.ca/~gary/rtmidi/
 +
* https://ccrma.stanford.edu/software/stk/classRtMidi.html

Versione attuale delle 10:39, 19 giu 2024

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.1.2.0.1

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