Guest User

foo_miditransport

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