示例#1
0
文件: piano.cpp 项目: nengxu/lmuse
void Piano::draw(QPainter& p, const QRect& r)
{
    QPoint offset(0, KH*2);
    p.drawTiledPixmap(r, *octave, r.topLeft()+offset);

    if (_curSelectedPitch != -1 && _curSelectedPitch != curPitch)
    {
        int y = pitch2y(_curSelectedPitch);
        QPixmap* pm;
        switch(_curSelectedPitch % 12) {
        case 0:
        case 5:
            pm = mk7;
            break;
        case 2:
        case 7:
        case 9:
            pm = mk6;
            break;
        case 4:
        case 11:
            pm = mk5;
            break;
        default:
            pm = mk8;
            break;
        }
        p.drawPixmap(0, y, *pm);
    }

    if (curPitch != -1)
    {
        int y = pitch2y(curPitch);
        QPixmap* pm;
        switch(curPitch % 12) {
        case 0:
        case 5:
            pm = mk3;
            break;
        case 2:
        case 7:
        case 9:
            pm = mk2;
            break;
        case 4:
        case 11:
            pm = mk1;
            break;
        default:
            pm = mk4;
            break;
        }
        p.drawPixmap(0, y, *pm);
    }

    // draw C notes
    for (int drawKey = 0; drawKey < 8; drawKey++) {
        int octaveSize=91;

        int drawY = octaveSize * drawKey + 82 - KH*2;
        if (drawY > r.y() && drawY < r.y() + r.height()) {
            p.drawPixmap(0,drawY,*c_keys[drawKey]);
        }
    }


    if(!_midiEditor)
        return;
    MusECore::PartList* part_list = _midiEditor->parts();
    MusECore::Part* cur_part = _midiEditor->curCanvasPart();
    if(!part_list || !cur_part)
        return;

    MusECore::MidiTrack* track = (MusECore::MidiTrack*)(cur_part->track());
    int channel      = track->outChannel();
    MusECore::MidiPort* port   = &MusEGlobal::midiPorts[track->outPort()];
    MusECore::MidiCtrlValListList* cll = port->controller();
    const int min = channel << 24;
    const int max = min + 0x1000000;

    for(MusECore::ciMidiCtrlValList it = cll->lower_bound(min); it != cll->lower_bound(max); ++it)
    {
        MusECore::MidiCtrlValList* cl = it->second;
        MusECore::MidiController* c   = port->midiController(cl->num());
        if(!c->isPerNoteController())
            continue;
        int cnum = c->num();
        int num = cl->num();
        int pitch = num & 0x7f;
        bool used = false;
        MusECore::EventList* el = cur_part->events();
        for (MusECore::ciEvent ie = el->begin(); ie != el->end(); ++ie)
        {
            MusECore::Event e = ie->second;
            if(e.type() != MusECore::Controller)
                continue;
            int ctl_num = e.dataA();
            if((ctl_num | 0xff) == cnum && (ctl_num & 0x7f) == pitch)
            {
                used = true;
                break;
            }
        }

        bool off = cl->hwVal() == MusECore::CTRL_VAL_UNKNOWN;  // Does it have a value or is it 'off'?

        int y = pitch2y(pitch) + 3;
        if(used)
        {
            if(off)
                p.drawPixmap(0, y, 6, 6, *greendot12x12Icon);
            else
                p.drawPixmap(0, y, 6, 6, *orangedot12x12Icon);
        }
        else
        {
            if(off)
                p.drawPixmap(0, y, 6, 6, *graydot12x12Icon);
            else
                p.drawPixmap(0, y, 6, 6, *bluedot12x12Icon);
        }
    }

}
示例#2
0
bool MusE::importMidi(const QString name, bool merge)
      {
      bool popenFlag;
      FILE* fp = MusEGui::fileOpen(this, name, QString(".mid"), "r", popenFlag);
      if (fp == 0)
            return true;
      MusECore::MidiFile mf(fp);
      bool rv = mf.read();
      popenFlag ? pclose(fp) : fclose(fp);
      if (rv) {
            QString s(tr("reading midifile\n  "));
            s += name;
            s += tr("\nfailed: ");
            s += mf.error();
            QMessageBox::critical(this, QString("MusE"), s);
            return rv;
            }
            
      MusECore::MidiFileTrackList* etl = mf.trackList();
      int division     = mf.division();

      // Find the default instrument, we may need it later...
      MusECore::MidiInstrument* def_instr = 0;
      if(!MusEGlobal::config.importMidiDefaultInstr.isEmpty())
      {
        for(MusECore::iMidiInstrument i = MusECore::midiInstruments.begin(); i != MusECore::midiInstruments.end(); ++i) 
        {
          if((*i)->iname() == MusEGlobal::config.importMidiDefaultInstr)   
          {
            def_instr = *i;
            break;
          }  
        }
      }
          
      //
      // Need to set up ports and instruments first
      //
      
      MusECore::MidiFilePortMap* usedPortMap = mf.usedPortMap();
      bool dev_changed = false;
      for(MusECore::iMidiFilePort imp = usedPortMap->begin(); imp != usedPortMap->end(); ++imp) 
      {
        MType midi_type = imp->second._midiType;
        QString instr_name = MusEGlobal::config.importInstrNameMetas ? imp->second._instrName : QString();
        MusECore::MidiInstrument* typed_instr = 0;
        MusECore::MidiInstrument* named_instr = 0;
        // Find a typed instrument and a named instrument, if requested
        for(MusECore::iMidiInstrument i = MusECore::midiInstruments.begin(); i != MusECore::midiInstruments.end(); ++i) 
        {
          MusECore::MidiInstrument* mi = *i;
          if(midi_type != MT_UNKNOWN && midi_type == mi->midiType())
            typed_instr = mi;
          if(!instr_name.isEmpty() && instr_name == mi->iname())
            named_instr = mi;
          if((typed_instr && named_instr) || ((typed_instr && instr_name.isEmpty()) || (named_instr && midi_type == MT_UNKNOWN)))
            break;  // Done searching
        }

        int port = imp->first;
        MusECore::MidiPort* mp = &MusEGlobal::midiPorts[port];
        MusECore::MidiDevice* md = mp->device();
        // Take care of assigning devices to empty ports here rather than in midifile.
        //if(MusEGlobal::config.importDevNameMetas)  // TODO
        {
          if(!md)
          {
            QString dev_name = imp->second._subst4DevName;
            md = MusEGlobal::midiDevices.find(dev_name); // Find any type of midi device - HW, synth etc.
            if(md)
            {
              // TEST: Hopefully shouldn't require any routing saves/restorations as in midi port config set device name...
              MusEGlobal::midiSeq->msgSetMidiDevice(mp, md);
              // TEST: Hopefully can get away with this ouside the loop below...
              //MusEGlobal::muse->changeConfig(true);     // save configuration file
              //MusEGlobal::audio->msgUpdateSoloStates();
              //MusEGlobal::song->update();
              dev_changed = true;
            }
            else
              printf("importMidi error: assign to empty port: device not found: %s\n", dev_name.toLatin1().constData());
          }
        }

        MusECore::MidiInstrument* instr = 0;
        // Priority is exact named instrument over a typed instrument.
        // This allows a named instrument plus a typed sysex, and the name will take priority. 
        // But it is possible that named mismatches may occur. So this named/typed order is user-selectable.
        if(named_instr && (!typed_instr || MusEGlobal::config.importInstrNameMetas))
        {
          instr = named_instr;
          if(MusEGlobal::debugMsg)
            printf("port:%d named instrument found:%s\n",
                    port, instr->iname().toLatin1().constData());
        }
        else if(typed_instr)
        {
        instr = typed_instr;
        if(MusEGlobal::debugMsg)
          printf("port:%d typed instrument found:%s\n",
                  port, instr->iname().toLatin1().constData());
        }
        else if(def_instr)
        {
          instr = def_instr;
          if(MusEGlobal::debugMsg)
            printf("port:%d no named or typed instrument found. Using default:%s\n",
                    port, instr->iname().toLatin1().constData());
        }
        else
        {
          instr = MusECore::genericMidiInstrument;
          if(MusEGlobal::debugMsg)
            printf("port:%d no named, typed, or default instrument found! Using:%s\n",
                    port, instr->iname().toLatin1().constData());
        }
        
        // If the instrument is one of the three standard GM, GS, or XG, mark the usedPort as "ch 10 is drums".
        // Otherwise it's anybody's guess what channel(s) drums are on.
        // Code is a bit HACKISH just to accomplish passing this bool value to the next stage, where tracks are created. 
        if(instr->midiType() != MT_UNKNOWN)
          imp->second._isStandardDrums = true;
          
        // Set the device's instrument - ONLY for non-synths because they provide their own. 
        if(!md || (md->deviceType() != MusECore::MidiDevice::SYNTH_MIDI))  
        {
          // this overwrites any instrument set for this port:
          if(mp->instrument() != instr)
            mp->setInstrument(instr);
        }
      }
      
      if(dev_changed)
      {
        // TEST: Hopefully can get away with this here instead of inside the loop above...
        // TEST: Are these really necessary as in midi port config set device name?
        MusEGlobal::muse->changeConfig(true);     // save configuration file 
        MusEGlobal::audio->msgUpdateSoloStates(); // 
        MusEGlobal::song->update();
      }
      
      //
      // create MidiTrack and copy events to ->events()
      //    - combine note on/off events
      //    - calculate tick value for internal resolution
      //
      for (MusECore::iMidiFileTrack t = etl->begin(); t != etl->end(); ++t) {
            MusECore::MPEventList& el  = ((*t)->events);
            if (el.empty())
                  continue;
            //
            // if we split the track, SYSEX and META events go into
            // the first target track

            bool first = true;
            
            // vastly changed by flo: replaced that silly loop
            // with that already_processed-set-check.
            // this makes stuff really fast :)
            
            MusECore::iMPEvent ev;
            set< pair<int,int> > already_processed;
            for (ev = el.begin(); ev != el.end(); ++ev)
            {
              if (ev->type() != MusECore::ME_SYSEX && ev->type() != MusECore::ME_META)
              {
                int channel=ev->channel();
                int port=ev->port();
                
                if (already_processed.find(pair<int,int>(channel, port)) == already_processed.end())
                {
                        already_processed.insert(pair<int,int>(channel, port));
                        
                        MusECore::MidiTrack* track = new MusECore::MidiTrack();
                        if ((*t)->_isDrumTrack)
                        {
                           if (MusEGlobal::config.importMidiNewStyleDrum)
                              track->setType(MusECore::Track::NEW_DRUM);
                           else
                              track->setType(MusECore::Track::DRUM);
                        }
                              
                        track->setOutChannel(channel);
                        track->setOutPort(port);

                        MusECore::MidiPort* mport = &MusEGlobal::midiPorts[port];
                        buildMidiEventList(&track->events, el, track, division, first, false); // Don't do loops.
                        first = false;

                        // Comment Added by T356.
                        // Hmm. buildMidiEventList already takes care of this. 
                        // But it seems to work. How? Must test. 
                        //if (channel == 9 && instr->midiType() != MT_UNKNOWN) {
                        MusECore::ciMidiFilePort imp = usedPortMap->find(port);
                        if(imp != usedPortMap->end() && imp->second._isStandardDrums && channel == 9) { // A bit HACKISH, see above
                           if (MusEGlobal::config.importMidiNewStyleDrum)
                              track->setType(MusECore::Track::NEW_DRUM);
                           else
                           {
                              track->setType(MusECore::Track::DRUM);
                              // remap drum pitch with drumOutmap (was: Inmap. flo93 thought this was wrong)
                              for (MusECore::iEvent i = track->events.begin(); i != track->events.end(); ++i) {
                                    MusECore::Event ev  = i->second;
                                    if (ev.isNote()) {
                                          int pitch = MusEGlobal::drumOutmap[ev.pitch()];
                                          ev.setPitch(pitch);
                                          }
                                    else
                                    if(ev.type() == MusECore::Controller)
                                    {
                                      int ctl = ev.dataA();
                                      MusECore::MidiController *mc = mport->drumController(ctl);
                                      if(mc)
                                        ev.setA((ctl & ~0xff) | MusEGlobal::drumOutmap[ctl & 0x7f]);
                                    }
                              }
                           }
                        }
                              
                        processTrack(track);
                        
                        MusEGlobal::song->insertTrack0(track, -1);
                }
              }
						}
						
            if (first) {
                  //
                  // track does only contain non-channel messages
                  // (SYSEX or META)
                  //
                  MusECore::MidiTrack* track = new MusECore::MidiTrack();
                  track->setOutChannel(0);
                  track->setOutPort(0);
                  buildMidiEventList(&track->events, el, track, division, true, false); // Do SysexMeta. Don't do loops.
                  processTrack(track);
                  MusEGlobal::song->insertTrack0(track, -1);
                  }
            }
            
      if (!merge) {
            MusECore::TrackList* tl = MusEGlobal::song->tracks();
            if (!tl->empty()) {
                  MusECore::Track* track = tl->front();
                  track->setSelected(true);
                  }
            MusEGlobal::song->initLen();

            int z, n;
            AL::sigmap.timesig(0, z, n);

            int tempo = MusEGlobal::tempomap.tempo(0);
            transport->setTimesig(z, n);
            transport->setTempo(tempo);

            bool masterF = !MusEGlobal::tempomap.empty();
            MusEGlobal::song->setMasterFlag(masterF);
            transport->setMasterFlag(masterF);

            MusEGlobal::song->updatePos();

            _arranger->reset();
            }
      else {
            MusEGlobal::song->initLen();
           }

      return false;
      }