Advertisement
Guest User

foo_miditransport

a guest
May 17th, 2015
104
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.05 KB | None | 0 0
  1. #include "stdafx.h"
  2. #include "MMSYSTEM.H"
  3.  
  4. #define MIDI_IN_DEV 5
  5.  
  6. DECLARE_COMPONENT_VERSION(
  7. "foo_miditransport",
  8. "0.0.1",
  9. "Add transport support from external MIDI interfaces such as MIDI controllers, keyboards, ...\n"
  10. "patrizio.boschi@gmail.com"
  11. );
  12.  
  13.  
  14.  
  15. /* Generic function to schedule a function from worker thread to be executed on main thread.
  16.     See Zao post @ http://www.hydrogenaud.io/forums/index.php?s=&showtopic=77922&view=findpost&p=680673 */
  17. template <typename F>
  18. void in_main_thread(F f)
  19. {
  20.     struct in_main : main_thread_callback
  21.     {
  22.         void callback_run() override
  23.         {
  24.             f();
  25.         }
  26.  
  27.         in_main(F f) : f(f) {}
  28.         F f;
  29.     };
  30.  
  31.     static_api_ptr_t<main_thread_callback_manager>()->add_callback(new service_impl_t<in_main>(f));
  32. }
  33.  
  34.  
  35.  
  36. static unsigned char CC_command, CC_value; // Parameters for executeCC
  37.  
  38. /* Handles the CC */
  39. void executeCC() {
  40.  
  41.     static_api_ptr_t<playback_control> pc;
  42.  
  43.     switch (CC_command) {
  44.     case 118:
  45.         if (CC_value == 127) pc->stop();
  46.         break;
  47.  
  48.     case 119:
  49.         if (CC_value == 127) pc->play_or_pause();
  50.         break;
  51.  
  52.     case 116:
  53.         if (CC_value == 127) pc->playback_seek_delta(-5);
  54.         break;
  55.    
  56.     case 117:
  57.         if (CC_value == 127) pc->playback_seek_delta(5);
  58.         break;
  59.     }
  60. }
  61.  
  62.  
  63.  
  64. /*
  65.     Check which MIDI command has been received and dispatches the corresponding method to handle it.
  66.     Refer to http://www.midi.org/techspecs/midimessages.php for MIDI protocol description
  67. */
  68. void dispatchCommand(DWORD dwParam1) {
  69.  
  70.     unsigned char status = LOBYTE(dwParam1);
  71.     unsigned char data1 = HIBYTE(dwParam1);
  72.     unsigned char data2 = LOBYTE(HIWORD(dwParam1));
  73.     unsigned char channel = status & 0x0F;
  74.     unsigned char message = (status & 0x70) >> 4;
  75.     std::string messageText;
  76.  
  77.     switch (message) {
  78.     case 0:
  79.         messageText = "Note Off";
  80.         break;
  81.  
  82.     case 1:
  83.         messageText = "Note On";
  84.         break;
  85.  
  86.     case 2:
  87.         messageText = "Aftertouch";
  88.         break;
  89.    
  90.     case 3:
  91.         messageText = "CC";
  92.         break;
  93.    
  94.     case 4:
  95.         messageText = "Program Change";
  96.         break;
  97.    
  98.     case 5:
  99.         messageText = "Channel Aftertouch";
  100.         break;
  101.    
  102.     case 6:
  103.         messageText = "Pitch Bend";
  104.         break;
  105.    
  106.     }
  107.  
  108.     console::formatter() << "MIDI IN - Channel: " << channel + 1 << " - Status: " << message << " (" << messageText.c_str() << ") - Data1: " << data1 << " Data2: " << data2;
  109.  
  110.     if (message == 3) { // CC command
  111.         CC_command = data1;
  112.         CC_value = data2;
  113.         in_main_thread(executeCC);
  114.     }
  115.  
  116.     /* TODO
  117.     other commands...
  118.     */
  119.  
  120. }
  121.  
  122.  
  123.  
  124. /* Callback called after every MIDI event */
  125. void CALLBACK midiCallback(HMIDIIN handle, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
  126. {
  127.     switch (uMsg)
  128.     {
  129.  
  130.     case MIM_DATA:
  131.         dispatchCommand(dwParam1);
  132.         break;
  133.     case MIM_OPEN:
  134.         console::formatter() << "MIDI OPEN";
  135.         break;
  136.     case MIM_CLOSE:
  137.         console::formatter() << "MIDI CLOSE";
  138.         break;
  139.     case MIM_ERROR:
  140.         console::formatter() << "MIDI ERROR";
  141.         break;
  142.     case MIM_LONGERROR:
  143.         console::formatter() << "MIDI LONGERROR";
  144.         break;
  145.     case MIM_MOREDATA:
  146.         console::formatter() << "MIDI MOREDATA";
  147.         break;
  148.     }
  149. }
  150.  
  151.  
  152.  
  153. class test : public initquit {
  154. public:
  155.     virtual void on_init()
  156.     {
  157.         unsigned int i, iNumDevs;
  158.         MIDIINCAPS mic;
  159.  
  160.         MMRESULT res;
  161.         HMIDIIN inHandle;
  162.  
  163.         /* Get the number of MIDI In devices in this computer */
  164.         iNumDevs = midiInGetNumDevs();
  165.  
  166.         /* Go through all of those devices, displaying their names */
  167.         for (i = 0; i < iNumDevs; i++)
  168.         {
  169.             /* Get info about the next device */
  170.             if (!midiInGetDevCaps(i, &mic, sizeof(MIDIINCAPS)))
  171.             {
  172.                 /* How to print a wstring? */
  173.                 std::wstring ws(mic.szPname);
  174.                 std::string str(ws.begin(), ws.end());
  175.                 console::formatter() << "Device ID #" << i << ": " << str.c_str();
  176.             }
  177.         }
  178.  
  179.         /* Open MIDI device and register callback */
  180.         res = midiInOpen(&inHandle, MIDI_IN_DEV, (DWORD_PTR)midiCallback, (DWORD_PTR)this, CALLBACK_FUNCTION);
  181.         if (res != MMSYSERR_NOERROR) {
  182.             console::formatter() << "midiInOpen error";
  183.             return;
  184.         }
  185.  
  186.         /* Start midi input */
  187.         res = midiInStart(inHandle);
  188.        
  189.     }
  190.  
  191.     virtual void on_quit()
  192.     {
  193.  
  194.     }
  195. };
  196.  
  197.  
  198.  
  199. initquit_factory_t<test> g_foo;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement