Пример #1
0
bool LOS::importMidi(const QString name, bool merge)/*{{{*/
{
    bool popenFlag;
    FILE* fp = fileOpen(this, name, QString(".mid"), "r", popenFlag);
    if (fp == 0)
        return true;
    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("LOS"), s);
        return rv;
    }
    //
    //  evaluate song Type (GM, XG, GS, unknown)
    //
    MidiType t = song->midiType();
    if (!merge)
    {
        t = mf.midiType();
        song->setMidiType(t);
    }
    MidiInstrument* instr = 0;
    for (iMidiInstrument i = midiInstruments.begin(); i != midiInstruments.end(); ++i)
    {
        MidiInstrument* mi = *i;
        if ((mi->iname() == "GM" && ((t == MIDI_TYPE_NULL) || (t == MIDI_TYPE_GM))) ||
            (mi->iname() == "GS" &&   t == MIDI_TYPE_GS) ||
            (mi->iname() == "XG" &&   t == MIDI_TYPE_XG))
        {
            instr = mi;
            break;
        }
    }
    if (instr == 0)
    {
        // the standard instrument files (GM, GS, XG) must be present
        printf("no instrument, type %d\n", t);
        return true;
        //abort();
    }

    MidiFileTrackList* etl = mf.trackList();
    int division = mf.division();

    //
    // create MidiTrack and copy events to ->events()
    //    - combine note on/off events
    //    - calculate tick value for internal resolution
    //
    int mPort = getFreeMidiPort();
    for (iMidiFileTrack t = etl->begin(); t != etl->end(); ++t)
    {
        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;
        QList<QPair<int, int> > portChannelList;
        iMPEvent i;
        for(i = el->begin(); i != el->end(); i++)
        {
            if (i->type() != ME_SYSEX && i->type() != ME_META)
            {
                int chan = i->channel();
                int port = i->port();
                if(portChannelList.isEmpty() || !portChannelList.contains(qMakePair(chan, port)))
                {
                    portChannelList.append(qMakePair(chan, port));

                    MidiTrack* track = new MidiTrack();
                    track->setDefaultName();
                    track->setMasterFlag(true);

                    if(config.partColorNames[lastTrackPartColorIndex].contains("menu:", Qt::CaseSensitive))
                        lastTrackPartColorIndex ++;

                    track->setDefaultPartColor(lastTrackPartColorIndex);
                    lastTrackPartColorIndex ++;

                    if(lastTrackPartColorIndex == NUM_PARTCOLORS)
                        lastTrackPartColorIndex = 1;

                    //Set track channel so buildMidiEventList can match the event to a channel
                    track->setOutChannel(chan);
                    track->setOutPort(mPort);

                    MidiPort* mport = &midiPorts[track->outPort()];
                    // this overwrites any instrument set for this port:
                    mport->setInstrument(instr);

                    EventList* mel = track->events();
                    buildMidiEventList(mel, el, track, division, first, false, false);

                    first = false;

                    processTrack(track);

                    //Update track to channel 1
                    //99% of all midi we import will be alien to our setup anyway,
                    //so I'm making it easy for the user to just set the Instrument and go
                    track->setOutChannel(0);

                    song->insertTrack(track, -1);
                    mPort++;
                    //FIXME: Provice a non-iterative way to do this using the new losMidiPorts hash
                    //Or maintain a list of configured or inuse ports
                    while((&midiPorts[mPort])->device() && mPort < kMaxMidiPorts)
                        mPort++;//Just incase we have a configured port after an empty one
                }
            }
        }
        if (first)
        {
            //
            // track does only contain non-channel messages
            // (SYSEX or META)
            //
            MidiTrack* track = new MidiTrack();
            track->setDefaultName();
            track->setMasterFlag(true);
            track->setOutChannel(0);
            track->setOutPort(mPort);

            if(config.partColorNames[lastTrackPartColorIndex].contains("menu:", Qt::CaseSensitive))
                lastTrackPartColorIndex ++;

            track->setDefaultPartColor(lastTrackPartColorIndex);
            lastTrackPartColorIndex ++;

            if(lastTrackPartColorIndex == NUM_PARTCOLORS)
                lastTrackPartColorIndex = 1;

            EventList* mel = track->events();
            // Do SysexMeta. Don't do loops.
            // TODO: Properly support sysex dumps
            buildMidiEventList(mel, el, track, division, true, false, false);
            processTrack(track);
            song->insertTrack(track, -1);
            mPort++;
            while((&midiPorts[mPort])->device() && mPort < kMaxMidiPorts)
                mPort++;
        }
    }

    if (!merge)
    {
        MidiTrackList* tl = song->tracks();
        if (!tl->empty())
        {
            MidiTrack* track = tl->front();
            track->setSelected(true);
        }
        song->initLen();

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

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

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

        song->updatePos();

        composer->reset();
    }
    else
    {
        song->initLen();
    }

    return false;
}/*}}}*/
Пример #2
0
void TrackListView::contextPopupMenu(QPoint pos)/*{{{*/
{
    QModelIndex mindex = m_table->indexAt(pos);
    if(!mindex.isValid())
        return;
    //int row = mindex.row();
    QStandardItem* item = m_model->itemFromIndex(mindex);
    if(item)
    {
        m_selectedIndex = item->row();
        //Make it works even if you rightclick on the checkbox
        QString trackName = item->data(TrackNameRole).toString();
        int type = item->data(TrackRole).toInt();
        MidiTrack* track = song->findTrack(trackName);
        if(!track || !m_editor)
            return;
        QMenu* p = new QMenu(this);
        QString title(tr("Part Color"));
        int index = track->getDefaultPartColor();
        Part* npart = 0;
        if(type == 1)
            title = QString(tr("Default Part Color"));
        else
        {
            PartList* list = track->parts();
            int sn = item->data(PartRole).toInt();
            unsigned tick = item->data(TickRole).toInt();
            npart = list->find(tick, sn);
            if(npart)
                index = npart->colorIndex();
        }
        QMenu* colorPopup = p->addMenu(title);

        QMenu* colorSub;
        for (int i = 0; i < NUM_PARTCOLORS; ++i)
        {
            QString colorname(config.partColorNames[i]);
            if(colorname.contains("menu:", Qt::CaseSensitive))
            {
                colorSub = colorPopup->addMenu(colorname.replace("menu:", ""));
            }
            else
            {
                if(index == i)
                {
                    colorname = QString(config.partColorNames[i]);
                    colorPopup->setIcon(partColorIconsSelected.at(i));
                    colorPopup->setTitle(colorSub->title()+": "+colorname);

                    colorname = QString("* "+config.partColorNames[i]);
                    QAction *act_color = colorSub->addAction(partColorIconsSelected.at(i), colorname);
                    act_color->setData(20 + i);
                }
                else
                {
                    colorname = QString("     "+config.partColorNames[i]);
                    QAction *act_color = colorSub->addAction(partColorIcons.at(i), colorname);
                    act_color->setData(20 + i);
                }
            }
        }
        p->addAction(tr("Add Part"))->setData(1);
        p->addAction(tr("Add Part and Select"))->setData(2);
        if(type == 2)
            p->addAction(tr("Delete Part"))->setData(3);

        QAction* act = p->exec(QCursor::pos());
        if (act)
        {
            int selection = act->data().toInt();
            switch(selection)
            {
                case 1:
                {
                    CItem *citem = los->composer->addCanvasPart(track);
                    if(citem)
                    {
                        Part* mp = citem->part();
                        populateTable();//update check state
                        //Select and scroll to the added part
                        if(mp)
                        {
                            int psn = mp->sn();
                            for(int i = 0; i < m_model->rowCount(); ++i)
                            {
                                QStandardItem* item = m_model->item(i, 0);
                                if(item)
                                {
                                    int type = item->data(TrackRole).toInt();
                                    if(type == 1)
                                    {//TrackMode
                                        continue;
                                    }
                                    else
                                    {//PartMode
                                        int sn = item->data(PartRole).toInt();
                                        if(psn == sn)
                                        {
                                            //m_tempColor = item->foreground();
                                            m_model->blockSignals(true);
                                            item->setForeground(QColor(99, 36, 36));
                                            m_model->blockSignals(false);
                                            update();
                                            m_selectedIndex = item->row();
                                            m_table->selectRow(m_selectedIndex);
                                            m_table->scrollTo(m_model->index(m_selectedIndex, 0));
                                            m_colorRows.append(m_selectedIndex);
                                            QTimer::singleShot(350, this, SLOT(updateColor()));
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                break;
                case 2:
                {
                    CItem* citem = los->composer->addCanvasPart(track);
                    if(citem)
                    {
                        Part* mp = citem->part();
                        if(mp)
                        {
                            m_editor->addPart(mp);
                            populateTable();//update check state
                            updatePartSelection(mp);
                        }
                    }
                    break;
                }
                case 3:
                {
                    if(npart)
                    {
                        audio->msgRemovePart(npart);
                        populateTable();//update check state
                        scrollPos = pos;
                        /*if(row < m_model->rowCount())
                        {
                            QModelIndex rowIndex = m_table->indexAt(pos);
                            m_table->scrollTo(rowIndex, QAbstractItemView::PositionAtTop);
                        }*/
                    }
                    break;
                }
                case 20 ... NUM_PARTCOLORS + 20:
                {
                    int curColorIndex = selection - 20;
                    if(npart)
                    {
                        npart->setColorIndex(curColorIndex);
                        song->update(SC_PART_COLOR_MODIFIED);
                    }
                    else
                    {
                        track->setDefaultPartColor(curColorIndex);
                    }
                    populateTable();//update check state
                    break;
                }
            }
        }
        delete p;
    }
}/*}}}*/