~ubuntu-branches/ubuntu/oneiric/muse/oneiric

« back to all changes in this revision

Viewing changes to muse/midi.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Fabrice Coutadeur
  • Date: 2010-11-17 21:43:38 UTC
  • mfrom: (1.1.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20101117214338-1hvfl7oo2dsqnvrb
Tags: 1.1-0ubuntu1
* New upstream release (LP: #668631)
* Switch to dpkg-source 3.0 (quilt) format
* Switch to dh7 short form
* debian/rules:
  - added --enable-dssi and --enable-osc to conf flags for dssi support
  - added -ljackserver to LDFLAGS to fix a FTBFS because of --as-needed
* debian/control:
  - added build build dependency on liblo-dev and dssi-dev for dssi support
  - bump Standards-version to 3.9.1. No changes required.
* debian/muse.desktop, debian/muse.xpm: dropped as desktop file and icon is
  now shipped upstream.
* fix-desktop-categories.patch: fix Categories tag in upstream desktop file
* 10_es_locale_fix.dpatch: refreshed and converted to quilt as
  fix_es_locale.patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
#include "audio.h"
24
24
#include "mididev.h"
25
25
#include "driver/alsamidi.h"
 
26
#include "driver/jackmidi.h"
26
27
#include "wave.h"
27
28
#include "synth.h"
28
29
#include "sync.h"
32
33
 
33
34
extern void dump(const unsigned char* p, int n);
34
35
 
35
 
const unsigned char gmOnMsg[] = { 0x7e, 0x7f, 0x09, 0x01 };
36
 
const unsigned char gsOnMsg[] = { 0x41, 0x10, 0x42, 0x12, 0x40, 0x00, 0x7f, 0x00, 0x41 };
37
 
const unsigned char xgOnMsg[] = { 0x43, 0x10, 0x4c, 0x00, 0x00, 0x7e, 0x00 };
38
 
const unsigned int  gmOnMsgLen = sizeof(gmOnMsg);
39
 
const unsigned int  gsOnMsgLen = sizeof(gsOnMsg);
40
 
const unsigned int  xgOnMsgLen = sizeof(xgOnMsg);
 
36
const unsigned char gmOnMsg[]   = { 0x7e, 0x7f, 0x09, 0x01 };
 
37
const unsigned char gsOnMsg[]   = { 0x41, 0x10, 0x42, 0x12, 0x40, 0x00, 0x7f, 0x00, 0x41 };
 
38
const unsigned char gsOnMsg2[]  = { 0x41, 0x10, 0x42, 0x12, 0x40, 0x01, 0x33, 0x50, 0x3c };
 
39
const unsigned char gsOnMsg3[]  = { 0x41, 0x10, 0x42, 0x12, 0x40, 0x01, 0x34, 0x50, 0x3b };
 
40
const unsigned char xgOnMsg[]   = { 0x43, 0x10, 0x4c, 0x00, 0x00, 0x7e, 0x00 };
 
41
const unsigned int  gmOnMsgLen  = sizeof(gmOnMsg);
 
42
const unsigned int  gsOnMsgLen  = sizeof(gsOnMsg);
 
43
const unsigned int  gsOnMsg2Len = sizeof(gsOnMsg2);
 
44
const unsigned int  gsOnMsg3Len = sizeof(gsOnMsg3);
 
45
const unsigned int  xgOnMsgLen  = sizeof(xgOnMsg);
 
46
 
 
47
const unsigned char mmcDeferredPlayMsg[] = { 0x7f, 0x7f, 0x06, 0x03 };
 
48
const unsigned char mmcStopMsg[] =         { 0x7f, 0x7f, 0x06, 0x01 };
 
49
const unsigned char mmcLocateMsg[] =       { 0x7f, 0x7f, 0x06, 0x44, 0x06, 0x01, 0, 0, 0, 0, 0 };
 
50
 
 
51
const unsigned int  mmcDeferredPlayMsgLen = sizeof(mmcDeferredPlayMsg);
 
52
const unsigned int  mmcStopMsgLen = sizeof(mmcStopMsg);
 
53
const unsigned int  mmcLocateMsgLen = sizeof(mmcLocateMsg);
41
54
 
42
55
#define CALC_TICK(the_tick) lrintf((float(the_tick) * float(config.division) + float(div/2)) / float(div));
43
56
/*---------------------------------------------------------
812
825
 
813
826
                              if (port == defaultPort) {
814
827
                                    //printf("Adding event normally: frame=%d port=%d channel=%d pitch=%d velo=%d\n",frame, port, channel, pitch, velo);
815
 
                                    playEvents->add(MidiPlayEvent(frame, port, channel, 0x90, pitch, velo));
 
828
                                    
 
829
                                    // p3.3.25
 
830
                                    // If syncing to external midi sync, we cannot use the tempo map.
 
831
                                    // Therefore we cannot get sub-tick resolution. Just use ticks instead of frames.
 
832
                                    if(extSyncFlag.value())
 
833
                                      playEvents->add(MidiPlayEvent(tick, port, channel, 0x90, pitch, velo));
 
834
                                    else
 
835
                                    
 
836
                                      playEvents->add(MidiPlayEvent(frame, port, channel, 0x90, pitch, velo));
 
837
                                      
816
838
                                    stuckNotes->add(MidiPlayEvent(tick + len, port, channel,
817
839
                                       veloOff ? 0x80 : 0x90, pitch, veloOff));
818
840
                                    }
819
841
                              else { //Handle events to different port than standard.
820
842
                                    MidiDevice* mdAlt = midiPorts[port].device();
821
843
                                    if (mdAlt) {
822
 
                                        mdAlt->playEvents()->add(MidiPlayEvent(frame, port, channel, 0x90, pitch, velo));
 
844
                                        
 
845
                                        // p3.3.25
 
846
                                        if(extSyncFlag.value())
 
847
                                          mdAlt->playEvents()->add(MidiPlayEvent(tick, port, channel, 0x90, pitch, velo));
 
848
                                        else  
 
849
                                          
 
850
                                          mdAlt->playEvents()->add(MidiPlayEvent(frame, port, channel, 0x90, pitch, velo));
 
851
                                          
823
852
                                        mdAlt->stuckNotes()->add(MidiPlayEvent(tick + len, port, channel,
824
853
                                          veloOff ? 0x80 : 0x90, pitch, veloOff));
825
854
                                      }
850
879
                                    MidiDevice* mdAlt = midiPorts[port].device();
851
880
                                    if(mdAlt) 
852
881
                                    {
853
 
                                      //playEvents->add(MidiPlayEvent(frame, port, channel, ev));
854
 
                                      mdAlt->playEvents()->add(MidiPlayEvent(frame, port, channel, 
855
 
                                                                             ME_CONTROLLER, ctl | pitch, ev.dataB()));
 
882
                                      // p3.3.25
 
883
                                      // If syncing to external midi sync, we cannot use the tempo map.
 
884
                                      // Therefore we cannot get sub-tick resolution. Just use ticks instead of frames.
 
885
                                      if(extSyncFlag.value())
 
886
                                        mdAlt->playEvents()->add(MidiPlayEvent(tick, port, channel, 
 
887
                                                                             ME_CONTROLLER, ctl | pitch, ev.dataB()));
 
888
                                      else
 
889
                                                                             
 
890
                                        //playEvents->add(MidiPlayEvent(frame, port, channel, ev));
 
891
                                        mdAlt->playEvents()->add(MidiPlayEvent(frame, port, channel, 
 
892
                                                                             ME_CONTROLLER, ctl | pitch, ev.dataB()));
 
893
                                                                             
856
894
                                    }  
857
895
                                    break;
858
896
                                  }  
859
897
                                }
860
 
                                playEvents->add(MidiPlayEvent(frame, port, channel, ev));
 
898
                                // p3.3.25
 
899
                                if(extSyncFlag.value())
 
900
                                  playEvents->add(MidiPlayEvent(tick, port, channel, ev));
 
901
                                else  
 
902
                                
 
903
                                  playEvents->add(MidiPlayEvent(frame, port, channel, ev));
861
904
                              }     
862
905
                              break;
863
906
                                   
864
907
                                   
865
908
                        default:
866
 
                              playEvents->add(MidiPlayEvent(frame, port, channel, ev));
 
909
                              // p3.3.25
 
910
                              if(extSyncFlag.value())
 
911
                                playEvents->add(MidiPlayEvent(tick, port, channel, ev));
 
912
                              else
 
913
                                
 
914
                                playEvents->add(MidiPlayEvent(frame, port, channel, ev));
 
915
                                
867
916
                              break;
868
917
                        }
869
918
                  }
896
945
            playEvents->erase(playEvents->begin(), nextPlayEvent);
897
946
 
898
947
            // klumsy hack for synti devices:
899
 
            if (!md->isSynti())
900
 
                  continue;
901
 
            SynthI* s = (SynthI*)md;
902
 
            while (s->eventsPending()) {
903
 
                  MidiRecordEvent ev = s->receiveEvent();
904
 
                  md->recordEvent(ev);
905
 
                  }
 
948
            if(md->isSynti())
 
949
            {
 
950
              SynthI* s = (SynthI*)md;
 
951
              while (s->eventsPending()) 
 
952
              {
 
953
                MidiRecordEvent ev = s->receiveEvent();
 
954
                md->recordEvent(ev);
 
955
              }
 
956
            }
 
957
            
 
958
            // Is it a Jack midi device? 
 
959
            //MidiJackDevice* mjd = dynamic_cast<MidiJackDevice*>(md);
 
960
            //if(mjd)
 
961
            //  mjd->collectMidiEvents();
 
962
            md->collectMidiEvents();
 
963
            
 
964
            // Take snapshots of the current sizes of the recording fifos, 
 
965
            //  because they may change while here in process, asynchronously.
 
966
            md->beforeProcess();
906
967
            }
907
968
 
908
969
      MPEventList* playEvents = metronome->playEvents();
909
970
      iMPEvent nextPlayEvent  = metronome->nextPlayEvent();
910
971
      playEvents->erase(playEvents->begin(), nextPlayEvent);
911
972
 
 
973
      // p3.3.25
 
974
      bool extsync = extSyncFlag.value();
 
975
      
912
976
      for (iMidiTrack t = song->midis()->begin(); t != song->midis()->end(); ++t) 
913
977
      {
914
978
            MidiTrack* track = *t;
941
1005
            if (track->recordFlag()) 
942
1006
            {
943
1007
                  //int portMask    = track->inPortMask();
944
 
                  unsigned int portMask = track->inPortMask();
945
 
                  int channelMask = track->inChannelMask();
 
1008
                  // p3.3.38 Removed
 
1009
                  //unsigned int portMask = track->inPortMask();
 
1010
                  //int channelMask = track->inChannelMask();
 
1011
                  
946
1012
                  MPEventList* rl = track->mpevents();
947
1013
                  MidiPort* tport = &midiPorts[port];
948
1014
 
949
 
                  for (iMidiDevice id = midiDevices.begin(); id != midiDevices.end(); ++id) 
 
1015
                  // p3.3.38
 
1016
                  //for (iMidiDevice id = midiDevices.begin(); id != midiDevices.end(); ++id) 
 
1017
                  //{
 
1018
                  RouteList* irl = track->inRoutes();
 
1019
                  for(ciRoute r = irl->begin(); r != irl->end(); ++r)
950
1020
                  {
951
 
                        MidiDevice* dev = *id;
952
 
 
953
 
                        int devport = dev->midiPort();
 
1021
                        //if(!r->isValid() || (r->type != Route::ALSA_MIDI_ROUTE && r->type != Route::JACK_MIDI_ROUTE))
 
1022
                        //if(!r->isValid() || (r->type != Route::MIDI_DEVICE_ROUTE))
 
1023
                        if(!r->isValid() || (r->type != Route::MIDI_PORT_ROUTE))   // p3.3.49
 
1024
                          continue;
 
1025
                           
 
1026
                        int devport = r->midiPort;     // p3.3.49
 
1027
                        if (devport == -1)
 
1028
                              continue;
 
1029
                        
 
1030
                        //MidiDevice* dev = *id;
 
1031
                        //MidiDevice* dev = r->device;
 
1032
                        MidiDevice* dev = midiPorts[devport].device();   // p3.3.49
 
1033
                        if(!dev)
 
1034
                          continue;
 
1035
                        
 
1036
                        
 
1037
                        // p3.3.50 Removed
 
1038
                        //int channel = r->channel;    
 
1039
                        // NOTE: TODO: Special for input device sysex 'channel' marked as -1, ** IF we end up going with that method **.
 
1040
                        // This would mean having a separate 'System' channel listed in the routing popups.
 
1041
                        // The other alternative is to accept sysex from a device as long as ANY regular channel is routed from it, 
 
1042
                        //  this does not require a 'System' channel listed in the routing popups.
 
1043
                        // But that requires more code below... Done.
 
1044
                        //if(channel == -1)
 
1045
                          //channel = MIDI_CHANNELS; // Special channel '17'
 
1046
                        //  continue;
 
1047
                          
 
1048
                        //int devport = dev->midiPort();
954
1049
                  
955
1050
                        // record only from ports marked in portMask:
956
 
                        if (devport == -1 || !(portMask & (1 << devport)))
957
 
                              continue;
 
1051
                        //if (devport == -1 || !(portMask & (1 << devport)))
 
1052
                        //if (devport == -1)
 
1053
                        //      continue;
958
1054
                              
959
 
                        MREventList* el = dev->recordEvents();
960
 
                        for (iMREvent ie = el->begin(); ie != el->end(); ++ie) 
 
1055
                        //MREventList* el = dev->recordEvents();
 
1056
                        //MidiFifo& rf = dev->recordEvents();
 
1057
                        
 
1058
                        
 
1059
                        int channelMask = r->channel;   // p3.3.50
 
1060
                        if(channelMask == -1 || channelMask == 0)
 
1061
                          continue;
 
1062
                        for(int channel = 0; channel < MIDI_CHANNELS; ++channel)     // p3.3.50
961
1063
                        {
962
 
                              int channel = ie->channel();
963
 
                              int defaultPort = devport;
964
 
                              if (!(channelMask & (1 << channel)))
965
 
                              {
966
 
                                    continue;
967
 
                              }      
968
 
 
969
 
                              MidiPlayEvent event(*ie);
970
 
                              int drumRecPitch=0; //prevent compiler warning: variable used without initialization
971
 
                              MidiController *mc = 0;
972
 
                              int ctl = 0;
973
 
                              
974
 
                              //Hmmm, hehhh... 
975
 
                              // TODO: Clean up a bit around here when it comes to separate events for rec & for playback. 
976
 
                              // But not before 0.7 (ml)
977
 
 
978
 
                              int prePitch = 0, preVelo = 0;
979
 
 
980
 
                              event.setChannel(track->outChannel());
981
 
                              
982
 
                              if (event.isNote() || event.isNoteOff()) 
983
 
                              {
984
 
                                    //
985
 
                                    // apply track values
986
 
                                    //
987
 
 
988
 
                                    //Apply drum inkey:
989
 
                                    if (track->type() == Track::DRUM) 
990
 
                                    {
991
 
                                          int pitch = event.dataA();
992
 
                                          //Map note that is played according to drumInmap
993
 
                                          drumRecPitch = drumMap[(unsigned int)drumInmap[pitch]].enote;
994
 
                                          devport = drumMap[(unsigned int)drumInmap[pitch]].port;
995
 
                                          event.setPort(devport);
996
 
                                          channel = drumMap[(unsigned int)drumInmap[pitch]].channel;
997
 
                                          event.setA(drumMap[(unsigned int)drumInmap[pitch]].anote);
998
 
                                          event.setChannel(channel);
999
 
                                    }
1000
 
                                    else 
1001
 
                                    { //Track transpose if non-drum
1002
 
                                          prePitch = event.dataA();
1003
 
                                          int pitch = prePitch + track->transposition;
1004
 
                                          if (pitch > 127)
1005
 
                                                pitch = 127;
1006
 
                                          if (pitch < 0)
1007
 
                                                pitch = 0;
1008
 
                                          event.setA(pitch);
1009
 
                                    }
1010
 
 
1011
 
                                    if (!event.isNoteOff()) 
1012
 
                                    {
1013
 
                                          preVelo = event.dataB();
1014
 
                                          int velo = preVelo + track->velocity;
1015
 
                                          velo = (velo * track->compression) / 100;
1016
 
                                          if (velo > 127)
1017
 
                                                velo = 127;
1018
 
                                          if (velo < 1)
1019
 
                                                velo = 1;
1020
 
                                          event.setB(velo);
1021
 
                                    }
1022
 
                              }
1023
 
                              // Added by T356.
1024
 
                              else
1025
 
                              if(event.type() == ME_CONTROLLER)
1026
 
                              {
1027
 
                                if(track->type() == Track::DRUM) 
1028
 
                                {
1029
 
                                  ctl = event.dataA();
1030
 
                                  // Regardless of what port the event came from, is it a drum controller event 
1031
 
                                  //  according to the track port's instrument?
1032
 
                                  mc = tport->drumController(ctl);
1033
 
                                  if(mc)
1034
 
                                  {
1035
 
                                    int pitch = ctl & 0x7f;
1036
 
                                    ctl &= ~0xff;
1037
 
                                    int dmindex = drumInmap[pitch] & 0x7f;
1038
 
                                    //Map note that is played according to drumInmap
1039
 
                                    drumRecPitch = drumMap[dmindex].enote;
1040
 
                                    devport = drumMap[dmindex].port;
1041
 
                                    event.setPort(devport);
1042
 
                                    channel = drumMap[dmindex].channel;
1043
 
                                    event.setA(ctl | drumMap[dmindex].anote);
1044
 
                                    event.setChannel(channel);
1045
 
                                  }  
1046
 
                                }
1047
 
                              }
1048
 
                              
1049
 
                              unsigned time = event.time() + segmentSize*(segmentCount-1);
1050
 
                              event.setTime(time);
1051
 
 
 
1064
                          if(!(channelMask & (1 << channel)))
 
1065
                            continue;
 
1066
                        
 
1067
                          if(!dev->sysexFIFOProcessed())
 
1068
                          {
 
1069
                            // Set to the sysex fifo at first.
 
1070
                            MidiFifo& rf = dev->recordEvents(MIDI_CHANNELS);
 
1071
                            // Get the frozen snapshot of the size.
 
1072
                            int count = dev->tmpRecordCount(MIDI_CHANNELS);
 
1073
                          
 
1074
                            for(int i = 0; i < count; ++i) 
 
1075
                            {
 
1076
                              MidiPlayEvent event(rf.peek(i));
 
1077
                              
 
1078
                              //unsigned time = event.time() + segmentSize*(segmentCount-1);
 
1079
                              //unsigned time = event.time() + (extsync ? config.division/24 : segmentSize*(segmentCount-1));
 
1080
                              //unsigned time = extsync ? curTickPos : (event.time() + segmentSize*(segmentCount-1));
 
1081
                              //event.setTime(time);
 
1082
                              //if(!extsync)
 
1083
                              //  event.setTime(event.time() + segmentSize*(segmentCount-1));
 
1084
  
 
1085
                              event.setPort(port);
 
1086
                              
1052
1087
                              // dont't echo controller changes back to software
1053
1088
                              // synthesizer:
1054
 
 
1055
 
                              if (!dev->isSynti()) 
1056
 
                              {
1057
 
                                // Added by Tim. p3.3.8
1058
 
                                if(track->recEcho())
1059
 
                                {
1060
 
                                
1061
 
                                  //Check if we're outputting to another port than default:
1062
 
                                  if (devport == defaultPort) {
1063
 
                                        event.setPort(port);
1064
 
                                        if(md)
1065
 
                                          playEvents->add(event);
1066
 
                                        }
1067
 
                                  else {
1068
 
                                        // Hmm, this appears to work, but... Will this induce trouble with md->setNextPlayEvent??
1069
 
                                        MidiDevice* mdAlt = midiPorts[devport].device();
1070
 
                                        if(mdAlt)
1071
 
                                          mdAlt->playEvents()->add(event);
1072
 
                                        }
1073
 
                                }
1074
 
                                // Shall we activate meters even while rec echo is off? Sure, why not...
1075
 
                                if(event.isNote() && event.dataB() > track->activity())
1076
 
                                  track->setActivity(event.dataB());
1077
 
                              }
 
1089
                              if(!dev->isSynti() && md && track->recEcho())
 
1090
                                playEvents->add(event);
1078
1091
                              
1079
 
                              time = tempomap.frame2tick(event.time());
1080
 
                              event.setTime(time);  // set tick time
1081
 
 
1082
 
                              // Special handling of events stored in rec-lists. a bit hACKish. TODO: Clean up (after 0.7)! :-/ (ml)
1083
 
                              if (recording) 
 
1092
                              // If syncing externally the event time is already in units of ticks, set above.
 
1093
                              if(!extsync)
1084
1094
                              {
1085
 
                                    // In these next steps, it is essential to set the recorded event's port 
1086
 
                                    //  to the track port so buildMidiEventList will accept it. Even though 
1087
 
                                    //  the port may have no device "<none>".
1088
 
                                    //
1089
 
                                    if (track->type() == Track::DRUM) 
 
1095
                                //time = tempomap.frame2tick(event.time());
 
1096
                                //event.setTime(time);  // set tick time
 
1097
                                event.setTime(tempomap.frame2tick(event.time()));  // set tick time
 
1098
                              }  
 
1099
  
 
1100
                              if(recording) 
 
1101
                                rl->add(event);
 
1102
                            }      
 
1103
                            
 
1104
                            dev->setSysexFIFOProcessed(true);
 
1105
                          }
 
1106
                          
 
1107
                          // Set to the sysex fifo at first.
 
1108
                          ///MidiFifo& rf = dev->recordEvents(MIDI_CHANNELS);
 
1109
                          // Get the frozen snapshot of the size.
 
1110
                          ///int count = dev->tmpRecordCount(MIDI_CHANNELS);
 
1111
                          
 
1112
                          // Iterate once for sysex fifo (if needed), once for channel fifos.
 
1113
                          ///for(int sei = 0; sei < 2; ++sei)
 
1114
                          {
 
1115
                            // If on first pass, do sysex fifo.  
 
1116
                            /*
 
1117
                            if(sei == 0)
 
1118
                            {  
 
1119
                              // Ignore any further channel routes on this device if already done here.
 
1120
                              if(dev->sysexFIFOProcessed())
 
1121
                                continue;
 
1122
                              // Go ahead and set this now.
 
1123
                              dev->setSysexFIFOProcessed(true);
 
1124
                              // Allow it to fall through with the sysex fifo and count...
 
1125
                            }
 
1126
                            else
 
1127
                            {
 
1128
                              // We're on the second pass, do channel fifos.
 
1129
                              rf = dev->recordEvents(channel);
 
1130
                              // Get the frozen snapshot of the size.
 
1131
                              count = dev->tmpRecordCount(channel);
 
1132
                            }
 
1133
                            */
 
1134
                            
 
1135
                            MidiFifo& rf = dev->recordEvents(channel);
 
1136
                            int count = dev->tmpRecordCount(channel);
 
1137
                            
 
1138
                            //for (iMREvent ie = el->begin(); ie != el->end(); ++ie) 
 
1139
                            for(int i = 0; i < count; ++i) 
 
1140
                            {
 
1141
                                  MidiPlayEvent event(rf.peek(i));
 
1142
                                  
 
1143
                                  //int channel = ie->channel();
 
1144
                                  ///int channel = event.channel();
 
1145
                                  
 
1146
                                  int defaultPort = devport;
 
1147
                                  ///if (!(channelMask & (1 << channel)))
 
1148
                                  ///{
 
1149
                                  ///      continue;
 
1150
                                  ///}      
 
1151
    
 
1152
                                  //MidiPlayEvent event(*ie);
 
1153
                                  int drumRecPitch=0; //prevent compiler warning: variable used without initialization
 
1154
                                  MidiController *mc = 0;
 
1155
                                  int ctl = 0;
 
1156
                                  
 
1157
                                  //Hmmm, hehhh... 
 
1158
                                  // TODO: Clean up a bit around here when it comes to separate events for rec & for playback. 
 
1159
                                  // But not before 0.7 (ml)
 
1160
    
 
1161
                                  int prePitch = 0, preVelo = 0;
 
1162
    
 
1163
                                  event.setChannel(track->outChannel());
 
1164
                                  
 
1165
                                  if (event.isNote() || event.isNoteOff()) 
 
1166
                                  {
 
1167
                                        //
 
1168
                                        // apply track values
 
1169
                                        //
 
1170
    
 
1171
                                        //Apply drum inkey:
 
1172
                                        if (track->type() == Track::DRUM) 
 
1173
                                        {
 
1174
                                              int pitch = event.dataA();
 
1175
                                              //Map note that is played according to drumInmap
 
1176
                                              drumRecPitch = drumMap[(unsigned int)drumInmap[pitch]].enote;
 
1177
                                              devport = drumMap[(unsigned int)drumInmap[pitch]].port;
 
1178
                                              event.setPort(devport);
 
1179
                                              channel = drumMap[(unsigned int)drumInmap[pitch]].channel;
 
1180
                                              event.setA(drumMap[(unsigned int)drumInmap[pitch]].anote);
 
1181
                                              event.setChannel(channel);
 
1182
                                        }
 
1183
                                        else 
 
1184
                                        { //Track transpose if non-drum
 
1185
                                              prePitch = event.dataA();
 
1186
                                              int pitch = prePitch + track->transposition;
 
1187
                                              if (pitch > 127)
 
1188
                                                    pitch = 127;
 
1189
                                              if (pitch < 0)
 
1190
                                                    pitch = 0;
 
1191
                                              event.setA(pitch);
 
1192
                                        }
 
1193
    
 
1194
                                        if (!event.isNoteOff()) 
 
1195
                                        {
 
1196
                                              preVelo = event.dataB();
 
1197
                                              int velo = preVelo + track->velocity;
 
1198
                                              velo = (velo * track->compression) / 100;
 
1199
                                              if (velo > 127)
 
1200
                                                    velo = 127;
 
1201
                                              if (velo < 1)
 
1202
                                                    velo = 1;
 
1203
                                              event.setB(velo);
 
1204
                                        }
 
1205
                                  }
 
1206
                                  // Added by T356.
 
1207
                                  else
 
1208
                                  if(event.type() == ME_CONTROLLER)
 
1209
                                  {
 
1210
                                    if(track->type() == Track::DRUM) 
1090
1211
                                    {
1091
 
                                      // Is it a drum controller event?
 
1212
                                      ctl = event.dataA();
 
1213
                                      // Regardless of what port the event came from, is it a drum controller event 
 
1214
                                      //  according to the track port's instrument?
 
1215
                                      mc = tport->drumController(ctl);
1092
1216
                                      if(mc)
1093
 
                                      {    
1094
 
                                          MidiPlayEvent drumRecEvent = event;
1095
 
                                          drumRecEvent.setA(ctl | drumRecPitch);
1096
 
                                          // In this case, preVelo is simply the controller value.
1097
 
                                          drumRecEvent.setB(preVelo);
1098
 
                                          drumRecEvent.setPort(port); //rec-event to current port
1099
 
                                          drumRecEvent.setChannel(track->outChannel()); //rec-event to current channel
1100
 
                                          rl->add(drumRecEvent);
1101
 
                                      }
1102
 
                                      else
1103
1217
                                      {
1104
 
                                      
1105
 
                                          MidiPlayEvent drumRecEvent = event;
1106
 
                                          drumRecEvent.setA(drumRecPitch);
1107
 
                                          drumRecEvent.setB(preVelo);
1108
 
                                          // Changed by T356. 
1109
 
                                          // Tested: Events were not being recorded for a drum map entry pointing to a 
1110
 
                                          //  different port. This must have been wrong - buildMidiEventList would ignore this.
1111
 
                                          //drumRecEvent.setPort(devport);
1112
 
                                          drumRecEvent.setPort(port);  //rec-event to current port
 
1218
                                        int pitch = ctl & 0x7f;
 
1219
                                        ctl &= ~0xff;
 
1220
                                        int dmindex = drumInmap[pitch] & 0x7f;
 
1221
                                        //Map note that is played according to drumInmap
 
1222
                                        drumRecPitch = drumMap[dmindex].enote;
 
1223
                                        devport = drumMap[dmindex].port;
 
1224
                                        event.setPort(devport);
 
1225
                                        channel = drumMap[dmindex].channel;
 
1226
                                        event.setA(ctl | drumMap[dmindex].anote);
 
1227
                                        event.setChannel(channel);
 
1228
                                      }  
 
1229
                                    }
 
1230
                                  }
 
1231
                                  
 
1232
                                  // p3.3.25 
 
1233
                                  // MusE uses a fixed clocks per quarternote of 24. 
 
1234
                                  // At standard 384 ticks per quarternote for example, 
 
1235
                                  // 384/24=16 for a division of 16 sub-frames (16 MusE 'ticks').
 
1236
                                  // That is what we'll use if syncing externally.
 
1237
                                  //unsigned time = event.time() + segmentSize*(segmentCount-1);
 
1238
                                  //unsigned time = event.time() + (extsync ? config.division/24 : segmentSize*(segmentCount-1));
 
1239
                                  // p3.3.34
 
1240
                                  // Oops, use the current tick. 
 
1241
                                  //unsigned time = extsync ? curTickPos : (event.time() + segmentSize*(segmentCount-1));
 
1242
                                  //event.setTime(time);
 
1243
                                  // p3.3.35
 
1244
                                  // If ext sync, events are now time-stamped with last tick in MidiDevice::recordEvent().
 
1245
                                  // TODO: Tested, but record resolution not so good. Switch to wall clock based separate list in MidiDevice.
 
1246
                                  // p3.3.36
 
1247
                                  //if(!extsync)
 
1248
                                  //  event.setTime(event.time() + segmentSize*(segmentCount-1));
 
1249
    
 
1250
                                  // dont't echo controller changes back to software
 
1251
                                  // synthesizer:
 
1252
    
 
1253
                                  if (!dev->isSynti()) 
 
1254
                                  {
 
1255
                                    //Check if we're outputting to another port than default:
 
1256
                                    if (devport == defaultPort) {
 
1257
                                          event.setPort(port);
 
1258
                                          if(md && track->recEcho())
 
1259
                                            playEvents->add(event);
 
1260
                                          }
 
1261
                                    else {
 
1262
                                          // Hmm, this appears to work, but... Will this induce trouble with md->setNextPlayEvent??
 
1263
                                          MidiDevice* mdAlt = midiPorts[devport].device();
 
1264
                                          if(mdAlt && track->recEcho())
 
1265
                                            mdAlt->playEvents()->add(event);
 
1266
                                          }
 
1267
                                    // Shall we activate meters even while rec echo is off? Sure, why not...
 
1268
                                    if(event.isNote() && event.dataB() > track->activity())
 
1269
                                      track->setActivity(event.dataB());
 
1270
                                  }
 
1271
                                  
 
1272
                                  // p3.3.25
 
1273
                                  // If syncing externally the event time is already in units of ticks, set above.
 
1274
                                  if(!extsync)
 
1275
                                  {
 
1276
                                    // p3.3.35
 
1277
                                    //time = tempomap.frame2tick(event.time());
 
1278
                                    //event.setTime(time);  // set tick time
 
1279
                                    event.setTime(tempomap.frame2tick(event.time()));  // set tick time
 
1280
                                  }  
 
1281
    
 
1282
                                  // Special handling of events stored in rec-lists. a bit hACKish. TODO: Clean up (after 0.7)! :-/ (ml)
 
1283
                                  if (recording) 
 
1284
                                  {
 
1285
                                        // In these next steps, it is essential to set the recorded event's port 
 
1286
                                        //  to the track port so buildMidiEventList will accept it. Even though 
 
1287
                                        //  the port may have no device "<none>".
 
1288
                                        //
 
1289
                                        if (track->type() == Track::DRUM) 
 
1290
                                        {
 
1291
                                          // Is it a drum controller event?
 
1292
                                          if(mc)
 
1293
                                          {    
 
1294
                                              MidiPlayEvent drumRecEvent = event;
 
1295
                                              drumRecEvent.setA(ctl | drumRecPitch);
 
1296
                                              // In this case, preVelo is simply the controller value.
 
1297
                                              drumRecEvent.setB(preVelo);
 
1298
                                              drumRecEvent.setPort(port); //rec-event to current port
 
1299
                                              drumRecEvent.setChannel(track->outChannel()); //rec-event to current channel
 
1300
                                              rl->add(drumRecEvent);
 
1301
                                          }
 
1302
                                          else
 
1303
                                          {
1113
1304
                                          
1114
 
                                          drumRecEvent.setChannel(track->outChannel()); //rec-event to current channel
1115
 
                                          rl->add(drumRecEvent);
1116
 
                                      }    
1117
 
                                    }
1118
 
                                    else 
1119
 
                                    {
1120
 
                                          // Restore record-pitch to non-transposed value since we don't want the note transposed twice next
1121
 
                                          MidiPlayEvent recEvent = event;
1122
 
                                          if (prePitch)
1123
 
                                                recEvent.setA(prePitch);
1124
 
                                          if (preVelo)
1125
 
                                                recEvent.setB(preVelo);
1126
 
                                          recEvent.setPort(port);
1127
 
                                          recEvent.setChannel(track->outChannel());
1128
 
                                                
1129
 
                                          rl->add(recEvent);
1130
 
                                    }
1131
 
                              }
 
1305
                                              MidiPlayEvent drumRecEvent = event;
 
1306
                                              drumRecEvent.setA(drumRecPitch);
 
1307
                                              drumRecEvent.setB(preVelo);
 
1308
                                              // Changed by T356. 
 
1309
                                              // Tested: Events were not being recorded for a drum map entry pointing to a 
 
1310
                                              //  different port. This must have been wrong - buildMidiEventList would ignore this.
 
1311
                                              //drumRecEvent.setPort(devport);
 
1312
                                              drumRecEvent.setPort(port);  //rec-event to current port
 
1313
                                              
 
1314
                                              drumRecEvent.setChannel(track->outChannel()); //rec-event to current channel
 
1315
                                              rl->add(drumRecEvent);
 
1316
                                          }    
 
1317
                                        }
 
1318
                                        else 
 
1319
                                        {
 
1320
                                              // Restore record-pitch to non-transposed value since we don't want the note transposed twice next
 
1321
                                              MidiPlayEvent recEvent = event;
 
1322
                                              if (prePitch)
 
1323
                                                    recEvent.setA(prePitch);
 
1324
                                              if (preVelo)
 
1325
                                                    recEvent.setB(preVelo);
 
1326
                                              recEvent.setPort(port);
 
1327
                                              recEvent.setChannel(track->outChannel());
 
1328
                                                    
 
1329
                                              rl->add(recEvent);
 
1330
                                        }
 
1331
                                  }
 
1332
                            }
 
1333
                          }  
1132
1334
                        }
1133
1335
                  }
1134
1336
            }
1146
1348
      //
1147
1349
      for (iMidiDevice id = midiDevices.begin(); id != midiDevices.end(); ++id) {
1148
1350
            MidiDevice* md = *id;
1149
 
            md->recordEvents()->clear();
1150
 
 
 
1351
            
 
1352
            ///md->recordEvents()->clear();
1151
1353
            // By T356. Done processing this rec buffer, now flip to the other one.
1152
 
            md->flipRecBuffer();
1153
 
            
 
1354
            ///md->flipRecBuffer();
 
1355
            // We are done with the 'frozen' recording fifos, remove the events. 
 
1356
            md->afterProcess();
1154
1357
            
1155
1358
            MPEventList* stuckNotes = md->stuckNotes();
1156
1359
            MPEventList* playEvents = md->playEvents();
1160
1363
                  if (k->time() >= nextTickPos)
1161
1364
                        break;
1162
1365
                  MidiPlayEvent ev(*k);
1163
 
                  int frame = tempomap.tick2frame(k->time()) + frameOffset;
1164
 
                  ev.setTime(frame);
 
1366
                  
 
1367
                  // p3.3.25
 
1368
                  //int frame = tempomap.tick2frame(k->time()) + frameOffset;
 
1369
                  if(extsync)
 
1370
                  {
 
1371
                    ev.setTime(k->time());
 
1372
                  }
 
1373
                  else
 
1374
                  {
 
1375
                    int frame = tempomap.tick2frame(k->time()) + frameOffset;
 
1376
                    ev.setTime(frame);
 
1377
                  }  
 
1378
                  
 
1379
                  // p3.3.25
 
1380
                  //ev.setTime(frame);
 
1381
                  
1165
1382
                  playEvents->add(ev);
1166
1383
                  }
1167
1384
            stuckNotes->erase(stuckNotes->begin(), k);
1193
1410
                  else if (state == PRECOUNT) {
1194
1411
                        isMeasure = (clickno % clicksMeasure) == 0;
1195
1412
                        }
1196
 
                  int frame = tempomap.tick2frame(midiClick) + frameOffset;
1197
 
                  MidiPlayEvent ev(frame, clickPort, clickChan, ME_NOTEON,
 
1413
                  // p3.3.25
 
1414
                  //int frame = tempomap.tick2frame(midiClick) + frameOffset;
 
1415
                  int evtime = extsync ? midiClick : tempomap.tick2frame(midiClick) + frameOffset;
 
1416
                  
 
1417
                  // p3.3.25
 
1418
                  //MidiPlayEvent ev(frame, clickPort, clickChan, ME_NOTEON,
 
1419
                  MidiPlayEvent ev(evtime, clickPort, clickChan, ME_NOTEON,
1198
1420
                     beatClickNote, beatClickVelo);
 
1421
                     
1199
1422
                  if (md) {
1200
 
                        MidiPlayEvent ev(frame, clickPort, clickChan, ME_NOTEON,
 
1423
                        // p3.3.25
 
1424
                        //MidiPlayEvent ev(frame, clickPort, clickChan, ME_NOTEON,
 
1425
                        MidiPlayEvent ev(evtime, clickPort, clickChan, ME_NOTEON,
1201
1426
                           beatClickNote, beatClickVelo);
 
1427
                        
1202
1428
                        if (isMeasure) {
1203
1429
                              ev.setA(measureClickNote);
1204
1430
                              ev.setB(measureClickVelo);
1206
1432
                        playEvents->add(ev);
1207
1433
                        }
1208
1434
                  if (audioClickFlag) {
1209
 
                        MidiPlayEvent ev1(frame, 0, 0, ME_NOTEON, 0, 0);
 
1435
                        // p3.3.25
 
1436
                        //MidiPlayEvent ev1(frame, 0, 0, ME_NOTEON, 0, 0);
 
1437
                        MidiPlayEvent ev1(evtime, 0, 0, ME_NOTEON, 0, 0);
 
1438
                        
1210
1439
                        ev1.setA(isMeasure ? 0 : 1);
1211
1440
                        metronome->playEvents()->add(ev1);
1212
1441
                        }
1213
1442
                  if (md) {
1214
1443
                        ev.setB(0);
1215
 
                        frame = tempomap.tick2frame(midiClick+20) + frameOffset;
 
1444
                        // p3.3.25
 
1445
                        // Removed. Why was this here?
 
1446
                        //frame = tempomap.tick2frame(midiClick+20) + frameOffset;
 
1447
                        //
 
1448
                        // Does it mean this should be changed too? 
 
1449
                        // No, stuck notes are in units of ticks, not frames like (normal, non-external) play events...
1216
1450
                        ev.setTime(midiClick+10);
 
1451
                        
1217
1452
                        if (md)
1218
1453
                              stuckNotes->add(ev);
1219
1454
                        }
1251
1486
                  stuckNotes->clear();
1252
1487
                  }
1253
1488
            }
 
1489
            
 
1490
            
 
1491
      // p3.3.36
 
1492
      //int tickpos = audio->tickPos();
 
1493
      //bool extsync = extSyncFlag.value();
 
1494
      //
 
1495
      // Special for Jack midi devices: Play all Jack midi events up to curFrame.
 
1496
      //
 
1497
      for(iMidiDevice id = midiDevices.begin(); id != midiDevices.end(); ++id) 
 
1498
      {
 
1499
        //MidiDevice* md = *id;
 
1500
        // Is it a Jack midi device?
 
1501
        //MidiJackDevice* mjd = dynamic_cast<MidiJackDevice*>(md);
 
1502
        //if(!mjd)
 
1503
        //  continue;
 
1504
        //mjd->processMidi();
 
1505
        (*id)->processMidi();
 
1506
        
 
1507
        /*
 
1508
        int port = md->midiPort();
 
1509
        MidiPort* mp = port != -1 ? &midiPorts[port] : 0;
 
1510
        MPEventList* el = md->playEvents();
 
1511
        if (el->empty())
 
1512
              continue;
 
1513
        iMPEvent i = md->nextPlayEvent();
 
1514
        for(; i != el->end(); ++i) 
 
1515
        {
 
1516
          // If syncing to external midi sync, we cannot use the tempo map.
 
1517
          // Therefore we cannot get sub-tick resolution. Just use ticks instead of frames.
 
1518
          //if(i->time() > curFrame) 
 
1519
          if(i->time() > (extsync ? tickpos : curFrame)) 
 
1520
          {
 
1521
            //printf("  curT %d  frame %d\n", i->time(), curFrame);
 
1522
            break; // skip this event
 
1523
          }
 
1524
 
 
1525
          if(mp) 
 
1526
          {
 
1527
            if(mp->sendEvent(*i))
 
1528
              break;
 
1529
          }
 
1530
          else 
 
1531
          {
 
1532
            if(md->putEvent(*i))
 
1533
              break;
 
1534
          }
 
1535
        }
 
1536
        md->setNextPlayEvent(i);
 
1537
        */
 
1538
      }
 
1539
            
1254
1540
      midiBusy=false;
1255
1541
      }
1256
1542