Esempio n. 1
0
File: route.cpp Progetto: 87maxi/oom
bool checkRoute(const QString& s, const QString& d)/*{{{*/
{
	Route src(s, false, -1);
	Route dst(d, true, -1);

	if (!(src.isValid() && dst.isValid()) || (src == dst))
		return false;
	if (src.type == Route::JACK_ROUTE)
	{
		if (dst.type == Route::TRACK_ROUTE)
		{
			if (dst.track->type() != Track::AUDIO_INPUT)
			{
				return false;
			}
			src.channel = dst.channel;
			RouteList* inRoutes = dst.track->inRoutes();
			for (iRoute i = inRoutes->begin(); i != inRoutes->end(); ++i)
			{
				if (*i == src)
				{ // route already there
					return false;
				}
			}
		}
		else if (dst.type == Route::MIDI_DEVICE_ROUTE)
		{
			src.channel = -1;
			RouteList* routes = dst.device->inRoutes();
			for (iRoute i = routes->begin(); i != routes->end(); ++i)
			{
				if (*i == src)
				{ // route already there
					return false;
				}
			}
		}
		else
			return false;
	}
	else if (dst.type == Route::JACK_ROUTE)
	{
		if (src.type == Route::TRACK_ROUTE)
		{
			if (src.track->type() != Track::AUDIO_OUTPUT)
			{
				return false;
			}
			RouteList* outRoutes = src.track->outRoutes();
			dst.channel = src.channel;
			for (iRoute i = outRoutes->begin(); i != outRoutes->end(); ++i)
			{
				if (*i == dst)
				{ // route already there
					return false;
				}
			}
		}
		else if (src.type == Route::MIDI_DEVICE_ROUTE)
		{
			RouteList* routes = src.device->outRoutes();
			dst.channel = -1;
			for (iRoute i = routes->begin(); i != routes->end(); ++i)
			{
				if (*i == dst)
				{ // route already there
					return false;
				}
			}
		}
		else
			return false;
	}
	else if (src.type == Route::MIDI_PORT_ROUTE) // p3.3.49
	{
		RouteList* outRoutes = midiPorts[src.midiPort].outRoutes();
		for (iRoute i = outRoutes->begin(); i != outRoutes->end(); ++i)
		{
			if (*i == dst)
			{ // route already there
				return false;
			}
		}
	}
	else
	{
		RouteList* outRoutes = (src.type == Route::MIDI_DEVICE_ROUTE) ? src.device->outRoutes() : src.track->outRoutes();

		for (iRoute i = outRoutes->begin(); i != outRoutes->end(); ++i)
		{
			if (*i == dst)
			{ // route already there
				return false;
			}
		}
	}
	return true;
}/*}}}*/
Esempio n. 2
0
File: route.cpp Progetto: 87maxi/oom
void addRoute(Route src, Route dst)/*{{{*/
{
//TODO: Add hooks to update the patchcanvas on success
//This should be conditionally checked so we dont update if the canvas is what made the connection

#ifdef ROUTE_DEBUG
	fprintf(stderr, "addRoute:\n");
#endif

	if (!src.isValid() || !dst.isValid())
	{
		if (!src.isValid())
			fprintf(stderr, "addRoute: invalid src\n");
		if (!dst.isValid())
			fprintf(stderr, "addRoute: invalid dst\n");
		return;
	}

	if (src.type == Route::JACK_ROUTE)
	{
		if (dst.type == Route::TRACK_ROUTE)
		{
			if (dst.track->type() != Track::AUDIO_INPUT)
			{
				fprintf(stderr, "addRoute: source is jack, dest:%s is track but not audio input\n", dst.track->name().toLatin1().constData());
				return;
			}
			if (dst.channel < 0)
			{
				fprintf(stderr, "addRoute: source is jack, dest:%s is track but invalid channel:%d\n", dst.track->name().toLatin1().constData(), dst.channel);
				return;
			}

			src.channel = dst.channel;
			RouteList* inRoutes = dst.track->inRoutes();
			for (iRoute i = inRoutes->begin(); i != inRoutes->end(); ++i)
			{
				if (*i == src) // route already there
				{
					fprintf(stderr, "addRoute: src track route already exists.\n");
					return;
				}
			}
#ifdef ROUTE_DEBUG
			fprintf(stderr, "addRoute: src Jack dst track name: %s pushing source route\n", dst.track->name().toLatin1().constData());
#endif
			inRoutes->push_back(src);
		}
		else if (dst.type == Route::MIDI_DEVICE_ROUTE)
		{
			if (dst.device->deviceType() == MidiDevice::JACK_MIDI)
			{
				src.channel = dst.channel;

				RouteList* routes = dst.device->inRoutes();
				for (iRoute i = routes->begin(); i != routes->end(); ++i)
				{
					if (*i == src) // route already there
					{
						fprintf(stderr, "addRoute: src Jack midi route already exists.\n");
						return;
					}
				}
#ifdef ROUTE_DEBUG
				fprintf(stderr, "addRoute: src Jack dst Jack midi name: %s pushing source route\n", dst.device->name().toLatin1().constData());
#endif
				routes->push_back(src);
			}
			else
			{
				fprintf(stderr, "addRoute: source is Jack, but destination is not jack midi - type:%d\n", dst.device->deviceType());
				return;
			}
		}
		else
		{
			fprintf(stderr, "addRoute: source is Jack, but destination is not track or midi - type:%d \n", dst.type);
			return;
		}
	}
	else if (dst.type == Route::JACK_ROUTE)
	{
		if (src.type == Route::TRACK_ROUTE)
		{
			if (src.track->type() != Track::AUDIO_OUTPUT)
			{
				fprintf(stderr, "addRoute: destination is jack, source is track but not audio output\n");
				return;
			}
			if (src.channel < 0)
			{
				fprintf(stderr, "addRoute: destination is jack, source:%s is track but invalid channel:%d\n", src.track->name().toLatin1().constData(), src.channel);
				return;
			}

			RouteList* outRoutes = src.track->outRoutes();
			dst.channel = src.channel;

			for (iRoute i = outRoutes->begin(); i != outRoutes->end(); ++i)
			{
				if (*i == dst) // route already there
				{
#ifdef ROUTE_DEBUG
					fprintf(stderr, "addRoute: dst track route already exists.\n");
#endif
					return;
				}
			}
#ifdef ROUTE_DEBUG
			fprintf(stderr, "addRoute: dst Jack src track name: %s pushing destination route\n", src.track->name().toLatin1().constData());
#endif
			outRoutes->push_back(dst);
		}
		else if (src.type == Route::MIDI_DEVICE_ROUTE)
		{
			if (src.device->deviceType() == MidiDevice::JACK_MIDI)
			{
				dst.channel = src.channel;

				RouteList* routes = src.device->outRoutes();
				for (iRoute i = routes->begin(); i != routes->end(); ++i)
				{
					if (*i == dst) // route already there
					{
						fprintf(stderr, "addRoute: dst Jack midi route already exists.\n");
						return;
					}
				}
#ifdef ROUTE_DEBUG
				fprintf(stderr, "addRoute: dst Jack src Jack midi name: %s pushing destination route\n", src.device->name().toLatin1().constData());
#endif
				routes->push_back(dst);
			}
			else
			{
				fprintf(stderr, "addRoute: destination is Jack, but source is not jack midi - type:%d\n", src.device->deviceType());
				return;
			}
		}
		else
		{
			fprintf(stderr, "addRoute: destination is Jack, but source is not track or midi - type:%d \n", src.type);
			return;
		}
	}
	else if (src.type == Route::MIDI_PORT_ROUTE) // p3.3.49
	{
		if (dst.type != Route::TRACK_ROUTE)
		{
			fprintf(stderr, "addRoute: source is midi port:%d, but destination is not track\n", src.midiPort);
			return;
		}
		if (dst.channel < 1 || dst.channel >= (1 << MIDI_CHANNELS))
		{
			fprintf(stderr, "addRoute: source is midi port:%d, but destination channel mask:%d out of range\n", src.midiPort, dst.channel);
			return;
		}

		MidiPort *mp = &midiPorts[src.midiPort];

		src.channel = dst.channel;
		RouteList* outRoutes = mp->outRoutes();
		iRoute ir = outRoutes->begin(); // p3.3.50
		for (; ir != outRoutes->end(); ++ir)
		{
			if (ir->type == Route::TRACK_ROUTE && ir->track == dst.track) // p3.3.50 Does a route to the track exist?
			{
				ir->channel |= dst.channel; // p3.3.50 Bitwise OR the desired channel bit with the existing bit mask.
				break;
			}
		}
#ifdef ROUTE_DEBUG
		fprintf(stderr, "addRoute: src midi port:%d dst track name:%s pushing dst and src routes\n", src.midiPort, dst.track->name().toLatin1().constData());
#endif

		if (ir == outRoutes->end()) // p3.3.50 Only if route not found, add the route, with the requested channel bits as mask to start with.
			outRoutes->push_back(dst);

		RouteList* inRoutes = dst.track->inRoutes();

		// p3.3.50 Make sure only one single route, with a channel mask, can ever exist.
		ir = inRoutes->begin();
		for (; ir != inRoutes->end(); ++ir)
		{
			if (ir->type == Route::MIDI_PORT_ROUTE && ir->midiPort == src.midiPort) // p3.3.50 Does a route to the midi port exist?
			{
				ir->channel |= src.channel; // p3.3.50 Bitwise OR the desired channel bit with the existing bit mask.
				break;
			}
		}

		if (ir == inRoutes->end()) // p3.3.50 Only if route not found, add the route, with the requested channel bits as mask to start with.
			inRoutes->push_back(src);
	}
	else if (dst.type == Route::MIDI_PORT_ROUTE) // p3.3.49
	{
		if (src.type != Route::TRACK_ROUTE)
		{
			fprintf(stderr, "addRoute: destination is midi port:%d, but source is not track\n", dst.midiPort);
			return;
		}
		if (src.channel < 1 || src.channel >= (1 << MIDI_CHANNELS))
		{
			fprintf(stderr, "addRoute: destination is midi port:%d, but source channel mask:%d out of range\n", dst.midiPort, src.channel);
			return;
		}

		dst.channel = src.channel;
		RouteList* outRoutes = src.track->outRoutes();

		iRoute ir = outRoutes->begin(); // p3.3.50
		for (; ir != outRoutes->end(); ++ir)
		{
			if (ir->type == Route::MIDI_PORT_ROUTE && ir->midiPort == dst.midiPort) // p3.3.50 Does a route to the midi port exist?
			{
				ir->channel |= dst.channel; // p3.3.50 Bitwise OR the desired channel bit with the existing bit mask.
				break;
			}
		}

		if (ir == outRoutes->end()) // p3.3.50 Only if route not found, add the route, with the requested channel bits as mask to start with.
			outRoutes->push_back(dst);

		MidiPort *mp = &midiPorts[dst.midiPort];

#ifdef ROUTE_DEBUG
		fprintf(stderr, "addRoute: src track:%s dst midi port:%d pushing dst and src routes\n", src.track->name().toLatin1().constData(), dst.midiPort);
#endif
		RouteList* inRoutes = mp->inRoutes();

		// p3.3.50 Make sure only one single route, with a channel mask, can ever exist.
		ir = inRoutes->begin();
		for (; ir != inRoutes->end(); ++ir)
		{
			if (ir->type == Route::TRACK_ROUTE && ir->track == src.track) // p3.3.50 Does a route to the track exist?
			{
				ir->channel |= src.channel; // p3.3.50 Bitwise OR the desired channel bit with the existing bit mask.
				break;
			}
		}

		if (ir == inRoutes->end()) // p3.3.50 Only if route not found, add the route, with the requested channel bits as mask to start with.
			inRoutes->push_back(src);
	}
	else
	{
		if (src.type != Route::TRACK_ROUTE || dst.type != Route::TRACK_ROUTE) // p3.3.49
		{
			fprintf(stderr, "addRoute: source or destination are not track routes\n");
			return;
		}

		{
			RouteList* outRoutes = src.track->outRoutes();

			//
			// Must enforce to ensure channel and channels are valid if defaults of -1 passed.
			//
			if (src.track->type() == Track::AUDIO_SOFTSYNTH)
			{
				if (src.channel == -1)
					src.channel = 0;
				if (src.channels == -1)
					src.channels = src.track->channels();
				dst.channel = src.channel;
				dst.channels = src.channels;
				dst.remoteChannel = src.remoteChannel;
			}

			for (iRoute i = outRoutes->begin(); i != outRoutes->end(); ++i)
			{
				if (*i == dst) // route already there
				{
					//#ifdef ROUTE_DEBUG
					fprintf(stderr, "addRoute: src track route already exists.\n");
					//#endif
					return;
				}
			}
			outRoutes->push_back(dst);
			RouteList* inRoutes;

			{
#ifdef ROUTE_DEBUG
				fprintf(stderr, "addRoute: src track ch:%d chs:%d remch:%d  dst track ch:%d chs:%d remch:%d name: %s pushing dest and source routes\n",
						src.channel, src.channels, src.remoteChannel, dst.channel, dst.channels, dst.remoteChannel, dst.track->name().toLatin1().constData());
#endif
				inRoutes = dst.track->inRoutes();
			}


			//
			// make sure AUDIO_AUX is processed last
			//
			if (src.track->type() == Track::AUDIO_AUX)
				inRoutes->push_back(src);
			else
				inRoutes->insert(inRoutes->begin(), src);
		}
	}
}/*}}}*/
Esempio n. 3
0
File: route.cpp Progetto: 87maxi/oom
void removeRoute(Route src, Route dst)/*{{{*/
{
//TODO: Add hooks to update the patchcanvas on success
//This should be conditionally checked so we dont update if the canvas is what made the connection
	if (src.type == Route::JACK_ROUTE)
	{
		if (!dst.isValid())
		{
			printf("removeRoute: source is jack, invalid destination\n");
			return;
		}

		if (dst.type == Route::TRACK_ROUTE)
		{
			if (dst.track->type() != Track::AUDIO_INPUT)
			{
				fprintf(stderr, "removeRoute: source is jack, destination is track but not audio input\n");
				// exit(-1);
				return;
			}
			RouteList* inRoutes = dst.track->inRoutes();
			iRoute i;
			for (i = inRoutes->begin(); i != inRoutes->end(); ++i)
			{
				if (*i == src)
				{
					inRoutes->erase(i);
					break;
				}
			}
		}
		else if (dst.type == Route::MIDI_DEVICE_ROUTE)
		{
			RouteList* routes = dst.device->inRoutes();
			iRoute i;
			for (i = routes->begin(); i != routes->end(); ++i)
			{
				if (*i == src)
				{
					routes->erase(i);
					break;
				}
			}
		}
		else
		{
			fprintf(stderr, "removeRoute: source is jack, destination unknown\n");
			return;
		}
	}
	else if (dst.type == Route::JACK_ROUTE)
	{
		if (!src.isValid())
		{
			printf("removeRoute: destination is jack, invalid source\n");
			return;
		}

		if (src.type == Route::TRACK_ROUTE)
		{
			if (src.track->type() != Track::AUDIO_OUTPUT)
			{
				fprintf(stderr, "removeRoute: destination is jack, source is track but not audio output\n");
				return;
			}
			RouteList* outRoutes = src.track->outRoutes();
			iRoute i;
			for (i = outRoutes->begin(); i != outRoutes->end(); ++i)
			{
				if (*i == dst)
				{
					outRoutes->erase(i);
					break;
				}
			}
		}
		else if (src.type == Route::MIDI_DEVICE_ROUTE)
		{
			RouteList* routes = src.device->outRoutes();
			iRoute i;
			for (i = routes->begin(); i != routes->end(); ++i)
			{
				if (*i == dst)
				{
					routes->erase(i);
					break;
				}
			}
		}
		else
		{
			fprintf(stderr, "removeRoute: destination is jack, source unknown\n");
			// exit(-1);
			return;
		}
	}
	else if (src.type == Route::MIDI_PORT_ROUTE) // p3.3.49
	{
		if (dst.type != Route::TRACK_ROUTE)
		{
			fprintf(stderr, "removeRoute: source is midi port:%d, but destination is not track\n", src.midiPort);
			return;
		}

		if (src.isValid())
		{
			MidiPort *mp = &midiPorts[src.midiPort];
			RouteList* outRoutes = mp->outRoutes();
			for (iRoute i = outRoutes->begin(); i != outRoutes->end(); ++i)
			{
				//if (*i == dst)
				if (i->type == Route::TRACK_ROUTE && i->track == dst.track) // p3.3.50 Is there a route to the track?
				{
					i->channel &= ~dst.channel; // p3.3.50 Unset the desired channel bits.
					if (i->channel == 0) // Only if there are no channel bits set, erase the route.
						outRoutes->erase(i);

					break; // For safety, keep looking and remove any more found.
					// No, must break, else crash. There should only be one route anyway...
				}
			}
		}
		else
			printf("removeRoute: source is midi port:%d but invalid\n", src.midiPort);

		if (dst.isValid())
		{
			RouteList* inRoutes = dst.track->inRoutes();
			for (iRoute i = inRoutes->begin(); i != inRoutes->end(); ++i)
			{
				if (i->type == Route::MIDI_PORT_ROUTE && i->midiPort == src.midiPort) // p3.3.50 Is there a route to the midi port?
				{
					i->channel &= ~src.channel; // p3.3.50 Unset the desired channel bits.
					if (i->channel == 0) // Only if there are no channel bits set, erase the route.
						inRoutes->erase(i);

					break; // For safety, keep looking and remove any more found.
					// No, must break, else crash. There should only be one route anyway...
				}
			}
		}
		else
			printf("removeRoute: source is midi port:%d but destination track invalid\n", src.midiPort);
	}
	else if (dst.type == Route::MIDI_PORT_ROUTE) // p3.3.49
	{
		if (src.type != Route::TRACK_ROUTE)
		{
			fprintf(stderr, "removeRoute: destination is midi port:%d, but source is not track\n", dst.midiPort);
			return;
		}

		if (src.isValid())
		{
			RouteList* outRoutes = src.track->outRoutes();
			for (iRoute i = outRoutes->begin(); i != outRoutes->end(); ++i)
			{
				if (i->type == Route::MIDI_PORT_ROUTE && i->midiPort == dst.midiPort) // p3.3.50 Is there a route to the midi port?
				{
					i->channel &= ~dst.channel; // p3.3.50 Unset the desired channel bits.
					if (i->channel == 0) // Only if there are no channel bits set, erase the route.
						outRoutes->erase(i);

					break; // For safety, keep looking and remove any more found.
					// No, must break, else crash. There should only be one route anyway...
				}
			}
		}
		else
			printf("removeRoute: destination is midi port:%d but source track is invalid\n", dst.midiPort);

		if (dst.isValid())
		{
			MidiPort *mp = &midiPorts[src.midiPort];
			RouteList* inRoutes = mp->inRoutes();
			for (iRoute i = inRoutes->begin(); i != inRoutes->end(); ++i)
			{
				if (i->type == Route::TRACK_ROUTE && i->track == src.track) // p3.3.50 Is there a route to the track?
				{
					i->channel &= ~src.channel; // p3.3.50 Unset the desired channel bits.
					if (i->channel == 0) // Only if there are no channel bits set, erase the route.
						inRoutes->erase(i);

					break; // For safety, keep looking and remove any more found.
					// No, must break, else crash. There should only be one route anyway...
				}
			}
		}
		else
			printf("removeRoute: destination is midi port:%d but invalid\n", dst.midiPort);
	}
	else
	{
		if (src.type != Route::TRACK_ROUTE || dst.type != Route::TRACK_ROUTE) // p3.3.49
		{
			fprintf(stderr, "removeRoute: source and destination are not tracks\n");
			return;
		}

		if (src.isValid())
		{
			RouteList* outRoutes = src.track->outRoutes();
			for (iRoute i = outRoutes->begin(); i != outRoutes->end(); ++i)
			{
				if ((*i).name() == dst.name())
				{
					outRoutes->erase(i);
					break;
				}
			}
		}
		else
			printf("removeRoute: source is track but invalid\n");

		if (dst.isValid())
		{
			RouteList* inRoutes = dst.track->inRoutes();
			for (iRoute i = inRoutes->begin(); i != inRoutes->end(); ++i)
			{
				if ((*i).name() == src.name())
				{
					inRoutes->erase(i);
					break;
				}
			}
		}
		else
			printf("removeRoute: source is track but destination invalid\n");
	}
}/*}}}*/
Esempio n. 4
0
bool WaveTrack::getData(unsigned framePos, int channels, unsigned nframe, float** bp)
      {
      bool have_data = false;
      if ((MusEGlobal::song->bounceTrack != this) && !noInRoute()) {
            RouteList* irl = inRoutes();
            for(ciRoute i = irl->begin(); i != irl->end(); ++i)
            {
              if(i->track->isMidiTrack())
                continue;

              ((AudioTrack*)i->track)->copyData(framePos, channels,
                                               i->channel,
                                               i->channels,
                                               nframe, bp, have_data);
              have_data = true;
            }
            
            if (recordFlag()) {
            //if (have_data && recordFlag()) {
                  //if (MusEGlobal::audio->isRecording() && recFile()) {
                  if (have_data && MusEGlobal::audio->isRecording() && recFile()) {
                        if (MusEGlobal::audio->freewheel()) {
                              }
                        else {
#ifdef _AUDIO_USE_TRUE_FRAME_
                              // TODO: Tested: This is the line that would be needed for Audio Inputs, 
                              //  because the data arrived in the previous period! Test OK, the waves are in sync.
                              // So we need to do Audio Inputs separately above, AND find a way to mix two overlapping
                              //  periods into the file! Nothing wrong with the FIFO per se, we could stamp overlapping
                              //  times. But the soundfile just writes, does not mix.
                              //if (fifo.put(channels, nframe, bp, MusEGlobal::audio->previousPos().frame()))
                              //
                              // Tested: This line is OK for track-to-track recording, the waves are in sync:
#endif                              
                              if (fifo.put(channels, nframe, bp, MusEGlobal::audio->pos().frame()))  
                                    printf("WaveTrack::getData(%d, %d, %d): fifo overrun\n",
                                       framePos, channels, nframe);
                              }
                        }
                  //return true;  // REMOVE Tim. Can't hear existing parts while recording, even while simply armed.
                  // FIXME TODO Remove this. But first code below needs to become ADDITIVE/REPLACING (don't just take over buffers).
                  return have_data;  
                  }
            }
      if (!MusEGlobal::audio->isPlaying())
            return false;
            //return have_data;
      
      if (MusEGlobal::audio->freewheel()) {

            // when freewheeling, read data direct from file:
            // Indicate do not seek file before each read.
            fetchData(framePos, nframe, bp, false);

            }
      else {
            unsigned pos;
            if (_prefetchFifo.get(channels, nframe, bp, &pos)) {
                  printf("WaveTrack::getData(%s) fifo underrun\n",
                      name().toLocal8Bit().constData());
                  return false;
                  }
            if (pos != framePos) {
                  if (MusEGlobal::debugMsg)
                        printf("fifo get error expected %d, got %d\n",
                            framePos, pos);
                  while (pos < framePos) {
                        if (_prefetchFifo.get(channels, nframe, bp, &pos)) {
                              printf("WaveTrack::getData(%s) fifo underrun\n",
                                  name().toLocal8Bit().constData());
                              return false;
                              }
                        }
                  }
            }
      return true;
      }
Esempio n. 5
0
void MPConfig::songChanged(int flags)
{
    // Is it simply a midi controller value adjustment? Forget it.
    if (flags == SC_MIDI_CONTROLLER)
        return;

    // Get currently selected index...
    int no = -1;
    QTableWidgetItem* sitem = mdevView->currentItem();
    if (sitem)
    {
        QString id = sitem->tableWidget()->item(sitem->row(), DEVCOL_NO)->text();
        no = atoi(id.toLatin1().constData()) - 1;
        if (no < 0 || no >= kMaxMidiPorts)
            no = -1;
    }

    sitem = 0;
    for (int i = kMaxMidiPorts - 1; i >= 0; --i)
    {
        mdevView->blockSignals(true); // otherwise itemChanged() is triggered and bad things happen.
        MidiPort* port = &midiPorts[i];
        MidiDevice* dev = port->device();
        QString s;
        s.setNum(i + 1);
        QTableWidgetItem* itemno = mdevView->item(i, DEVCOL_NO);
        QTableWidgetItem* itemstate = mdevView->item(i, DEVCOL_STATE);
        itemstate->setText(port->state());
        QTableWidgetItem* iteminstr = mdevView->item(i, DEVCOL_INSTR);
        QString instrumentName = port->instrument() ? port->instrument()->iname() : tr("<unknown>");
        iteminstr->setText(instrumentName);
        iteminstr->setToolTip(instrumentName);
        QTableWidgetItem* itemname = mdevView->item(i, DEVCOL_NAME);
        QTableWidgetItem* itemgui = mdevView->item(i, DEVCOL_GUI);
        QTableWidgetItem* itemfb = mdevView->item(i, DEVCOL_CACHE_NRPN);
        QTableWidgetItem* itemrec = mdevView->item(i, DEVCOL_REC);
        QTableWidgetItem* itemplay = mdevView->item(i, DEVCOL_PLAY);
        QTableWidgetItem* itemout = mdevView->item(i, DEVCOL_OUTROUTES);
        QTableWidgetItem* itemin = mdevView->item(i, DEVCOL_INROUTES);
        QTableWidgetItem* itemdefin = mdevView->item(i, DEVCOL_DEF_IN_CHANS);
        itemdefin->setText(bitmap2String(port->defaultInChannels()));
        QTableWidgetItem* itemdefout = mdevView->item(i, DEVCOL_DEF_OUT_CHANS);
        itemdefout->setText(bitmap2String(port->defaultOutChannels()));
        mdevView->blockSignals(false);


        if (dev)
        {
            itemname->setText(dev->name());
            itemname->setToolTip(dev->name());

            // Is it a Jack midi device? Allow renaming.
            //if(dynamic_cast<MidiJackDevice*>(dev))
            if (dev->deviceType() == MidiDevice::JACK_MIDI)
                itemname->setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled);

            if (dev->rwFlags() & 0x2)
            {
                itemrec->setIcon(dev->openFlags() & 2 ? QIcon(*dotIcon) : QIcon(*dothIcon));
            }
            else
            {
                itemrec->setIcon(QIcon(QPixmap()));
            }

            if (dev->rwFlags() & 0x1)
            {
                itemplay->setIcon(dev->openFlags() & 1 ? QIcon(*dotIcon) : QIcon(*dothIcon));
            }
            else
                itemplay->setIcon(QIcon(QPixmap()));
            itemfb->setIcon(dev->cacheNRPN() ? QIcon(*dotIcon) : QIcon(*dothIcon));
        }
        else
        {
            itemname->setText(tr("<none>"));
            itemname->setToolTip("");
            itemgui->setIcon(QIcon(*dothIcon));
            itemrec->setIcon(QIcon(QPixmap()));
            itemplay->setIcon(QIcon(QPixmap()));
            itemfb->setIcon(QIcon(QPixmap()));
        }
        // falkTX, we don't want this in the connections manager
        //if (port->hasGui())
        //{
        //	itemgui->setIcon(port->guiVisible() ? QIcon(*dotIcon) : QIcon(*dothIcon));
        //}
        //else
        //{
            itemgui->setIcon(QIcon(QPixmap()));
        //}
        iteminstr->setIcon(QIcon(*buttondownIcon));
        itemname->setIcon(QIcon(*buttondownIcon));

        //if(dev && dynamic_cast<MidiJackDevice*>(dev))
        if (dev && dev->deviceType() == MidiDevice::JACK_MIDI)
        {
            //item->setPixmap(DEVCOL_ROUTES, *buttondownIcon);
            //item->setText(DEVCOL_ROUTES, tr("routes"));

            // p3.3.55
            if (dev->rwFlags() & 1)
                //if(dev->openFlags() & 1)
            {
                itemout->setIcon(QIcon(*buttondownIcon));
                if (port->device() && !port->device()->outRoutes()->empty())
                {
                    RouteList* list = port->device()->outRoutes();
                    if (!list->empty())
                    {
                        iRoute r = list->begin();
                        itemout->setText(r->name());
                    }
                }
                else
                {
                    itemout->setText(tr("out"));
                }

                //if (dev->openFlags() & 1)
                //	itemout->setText(tr("out"));
            }
            if (dev->rwFlags() & 2)
                //if(dev->openFlags() & 2)
            {
                itemin->setIcon(QIcon(*buttondownIcon));
                if (dev->openFlags() & 2)
                    itemin->setText(tr("in"));
            }
        }

        if (i == no) sitem = itemno;
    }

    if (sitem)
    {
        mdevView->setCurrentItem(sitem);
    }
}
Esempio n. 6
0
void MPConfig::rbClicked(QTableWidgetItem* item)
{
    if (item == 0)
        return;
    QString id = item->tableWidget()->item(item->row(), DEVCOL_NO)->text();
    int no = atoi(id.toLatin1().constData()) - 1;
    if (no < 0 || no >= kMaxMidiPorts)
        return;

    int n;
    MidiPort* port = &midiPorts[no];
    MidiDevice* dev = port->device();
    int rwFlags = dev ? dev->rwFlags() : 0;
    int openFlags = dev ? dev->openFlags() : 0;
    QTableWidget* listView = item->tableWidget();
    QPoint ppt = listView->visualItemRect(item).bottomLeft();
    QPoint mousepos = QCursor::pos();

    int col = item->column();
    ppt += QPoint(0, listView->horizontalHeader()->height());

    ppt = listView->mapToGlobal(ppt);

    switch (col)
    {
        case DEVCOL_GUI:
            if (dev == 0)
                //break;
                return;
            // falkTX, we don't want this in the connections manager
            //if (port->hasGui())
            //{
            //	port->instrument()->showGui(!port->guiVisible());
            //	item->setIcon(port->guiVisible() ? QIcon(*dotIcon) : QIcon(*dothIcon));
            //}
            //break;
            return;

        case DEVCOL_CACHE_NRPN:
            if (!dev)
                return;
            dev->setCacheNRPN(!dev->cacheNRPN());
            item->setIcon(dev->cacheNRPN() ? QIcon(*dotIcon) : QIcon(*dothIcon));

            return;

        case DEVCOL_REC:
            if (dev == 0 || !(rwFlags & 2))
                return;
            openFlags ^= 0x2;
            dev->setOpenFlags(openFlags);
            midiSeq->msgSetMidiDevice(port, dev); // reopen device
            item->setIcon(openFlags & 2 ? QIcon(*dotIcon) : QIcon(*dothIcon));

            if (dev->deviceType() == MidiDevice::JACK_MIDI)
            {
                if (dev->openFlags() & 2)
                {
                    item->tableWidget()->item(item->row(), DEVCOL_INROUTES)->setText(tr("in"));
                }
                else
                {
                    item->tableWidget()->item(item->row(), DEVCOL_INROUTES)->setText("");
                }
            }

            return;

        case DEVCOL_PLAY:
            if (dev == 0 || !(rwFlags & 1))
                return;
            openFlags ^= 0x1;
            dev->setOpenFlags(openFlags);
            midiSeq->msgSetMidiDevice(port, dev); // reopen device
            item->setIcon(openFlags & 1 ? QIcon(*dotIcon) : QIcon(*dothIcon));

            if (dev->deviceType() == MidiDevice::JACK_MIDI)
            {
                if (dev->openFlags() & 1)
                {
                    item->tableWidget()->item(item->row(), DEVCOL_OUTROUTES)->setText(tr("out"));
                }
                else
                {
                    item->tableWidget()->item(item->row(), DEVCOL_OUTROUTES)->setText("");
                }
            }

            return;

        case DEVCOL_INROUTES:
        case DEVCOL_OUTROUTES:
        {
            if (!checkAudioDevice())
                return;

            if (audioDevice->deviceType() != AudioDevice::JACK_AUDIO) //Only if Jack is running.
                return;

            if (!dev)
                return;

            // Only Jack midi devices.
            if (dev->deviceType() != MidiDevice::JACK_MIDI)
                return;

            if (!(dev->openFlags() & ((col == DEVCOL_OUTROUTES) ? 1 : 2)))
                return;

            RouteList* rl = (col == DEVCOL_OUTROUTES) ? dev->outRoutes() : dev->inRoutes(); // p3.3.55
            QMenu* pup = 0;
            int gid = 0;
            std::list<QString> sl;
            pup = new QMenu(this);
            //A temporary Route to us for matching later
            QString currentRoute("");
            bool routeSelected = false;

_redisplay:
            pup->clear();
            gid = 0;

            // Jack input ports if device is writable, and jack output ports if device is readable.
            sl = (col == DEVCOL_OUTROUTES) ? audioDevice->inputPorts(true, _showAliases) : audioDevice->outputPorts(true, _showAliases);

            QAction* act;

            act = pup->addAction(tr("Show first aliases"));
            act->setData(gid);
            act->setCheckable(true);
            act->setChecked(_showAliases == 0);
            ++gid;

            act = pup->addAction(tr("Show second aliases"));
            act->setData(gid);
            act->setCheckable(true);
            act->setChecked(_showAliases == 1);
            ++gid;

            pup->addSeparator();
            for (std::list<QString>::iterator ip = sl.begin(); ip != sl.end(); ++ip)
            {
                act = pup->addAction(*ip);
                act->setData(gid);
                act->setCheckable(true);

                Route rt(*ip, (col == DEVCOL_OUTROUTES), -1, Route::JACK_ROUTE);
                for (iRoute ir = rl->begin(); ir != rl->end(); ++ir)
                {
                    if (*ir == rt)
                    {
                        currentRoute = (*ir).name();
                        act->setChecked(true);
                        routeSelected = true;
                        break;
                    }
                }
                ++gid;
            }

            act = pup->exec(ppt);
            if (act)
            {
                n = act->data().toInt();
                if (n == 0) // Show first aliases
                {
                    if (_showAliases == 0)
                        _showAliases = -1;
                    else
                        _showAliases = 0;
                    goto _redisplay; // Go back
                }
                else if (n == 1) // Show second aliases
                {
                    if (_showAliases == 1)
                        _showAliases = -1;
                    else
                        _showAliases = 1;
                    goto _redisplay; // Go back
                }

                QString s(act->text());

                if (col == DEVCOL_OUTROUTES) // Writable
                {
                    Route srcRoute(dev, -1);
                    Route dstRoute(s, true, -1, Route::JACK_ROUTE);
                    if(routeSelected && currentRoute == s)
                    {
                        //it will alread be handled by an unchecked operation
                        routeSelected = false;
                    }

                    iRoute iir = rl->begin();
                    for (; iir != rl->end(); ++iir)
                    {
                        if (*iir == dstRoute)
                            break;
                    }

                    if (iir != rl->end())
                    {
                        // disconnect
                        audio->msgRemoveRoute(srcRoute, dstRoute);
                    }
                    else
                    {
                        // connect
                        audio->msgAddRoute(srcRoute, dstRoute);
                    }
                    if(routeSelected)
                    {
                        iRoute selr = rl->begin();
                        for (; selr != rl->end(); ++selr)
                        {
                            //clean up the routing list as something was selected that was not the current so delete the old route
                            if((*selr).name() == currentRoute)
                            {
                                audio->msgRemoveRoute(srcRoute, (*selr));
                                break;
                            }
                        }
                    }

                }
                else
                {
                    Route srcRoute(s, false, -1, Route::JACK_ROUTE);
                    Route dstRoute(dev, -1);

                    iRoute iir = rl->begin();
                    for (; iir != rl->end(); ++iir)
                    {
                        if (*iir == srcRoute)
                            break;
                    }
                    if (iir != rl->end())
                        // disconnect
                        audio->msgRemoveRoute(srcRoute, dstRoute);
                    else
                        // connect
                        audio->msgAddRoute(srcRoute, dstRoute);
                }

                audio->msgUpdateSoloStates();
                song->update(SC_ROUTE);
            }

            delete pup;
        }
            return;

        case DEVCOL_DEF_IN_CHANS:
        case DEVCOL_DEF_OUT_CHANS:
        {
        }
            //break;
            return;

        case DEVCOL_NAME:
        {
            //printf("MPConfig::rbClicked DEVCOL_NAME\n");

            // Did we click in the text area?
            // NOTE: this needs the +15 pixels to make up for padding in the stylesheet.
            if ((mousepos.x() - (ppt.x() + 15)) > buttondownIcon->width())
            {
                // Start the renaming of the cell...
                QModelIndex current = item->tableWidget()->currentIndex();
                if (item->flags() & Qt::ItemIsEditable)
                    item->tableWidget()->edit(current.sibling(current.row(), DEVCOL_NAME));

                return;
            }
            else
            {// We clicked the 'down' button.
                QMenu* pup = new QMenu(this);

                QAction* act;

                act = pup->addAction(tr("Create") + QT_TRANSLATE_NOOP("@default", " Jack") + tr(" device"));
                act->setData(0);

                typedef std::map<std::string, int > asmap;
                typedef std::map<std::string, int >::iterator imap;

                asmap mapALSA;
                asmap mapJACK;

                int aix = 0x10000000;
                int jix = 0x20000000;
                for (iMidiDevice i = midiDevices.begin(); i != midiDevices.end(); ++i)
                {
                    if ((*i)->deviceType() == MidiDevice::ALSA_MIDI)
                    {
                        mapALSA.insert(std::pair<std::string, int> (std::string((*i)->name().toLatin1().constData()), aix));
                        ++aix;
                    }
                    else if ((*i)->deviceType() == MidiDevice::JACK_MIDI)
                    {
                        mapJACK.insert(std::pair<std::string, int> (std::string((*i)->name().toLatin1().constData()), jix));
                        ++jix;
                    }
                    else
                        printf("MPConfig::rbClicked unknown midi device: %s\n", (*i)->name().toLatin1().constData());
                }

                pup->addSeparator();
                pup->addAction(new MenuTitleItem(QT_TRANSLATE_NOOP("@default", "ALSA:"), pup));

                for (imap i = mapALSA.begin(); i != mapALSA.end(); ++i)
                {
                    int idx = i->second;
                    QString s(i->first.c_str());
                    MidiDevice* md = midiDevices.find(s, MidiDevice::ALSA_MIDI);
                    if (md)
                    {
                        if (md->deviceType() != MidiDevice::ALSA_MIDI)
                            continue;

                        act = pup->addAction(QT_TRANSLATE_NOOP("@default", md->name()));
                        act->setData(idx);
                        act->setCheckable(true);
                        act->setChecked(md == dev);
                    }
                }

                pup->addSeparator();
                pup->addAction(new MenuTitleItem(QT_TRANSLATE_NOOP("@default", "JACK:"), pup));

                for (imap i = mapJACK.begin(); i != mapJACK.end(); ++i)
                {
                    int idx = i->second;
                    QString s(i->first.c_str());
                    MidiDevice* md = midiDevices.find(s, MidiDevice::JACK_MIDI);
                    if (md)
                    {
                        if (md->deviceType() != MidiDevice::JACK_MIDI)
                            continue;

                        act = pup->addAction(QT_TRANSLATE_NOOP("@default", md->name()));
                        act->setData(idx);
                        act->setCheckable(true);
                        act->setChecked(md == dev);
                    }
                }

                act = pup->exec(ppt);
                if (!act)
                {
                    delete pup;
                    return;
                }

                n = act->data().toInt();
                //printf("MPConfig::rbClicked n:%d\n", n);

                MidiDevice* sdev = 0;
                if (n < 0x10000000)
                {
                    delete pup;
                    if (n <= 2)
                    {
                        sdev = MidiJackDevice::createJackMidiDevice();

                        if (sdev)
                        {
                            int of = 3;
                            switch (n)
                            {
                                case 0: of = 0; //3; Set the open flags of the midiDevice this should be off by default
                                    break;
                                case 1: of = 2;
                                    break;
                                case 2: of = 1;
                                    break;
                            }
                            sdev->setOpenFlags(of);
                        }
                    }
                }
                else
                {
                    int typ;
                    if (n < 0x20000000)
                        typ = MidiDevice::ALSA_MIDI;
                    else if (n < 0x30000000)
                        typ = MidiDevice::JACK_MIDI;
                    else
                        typ = MidiDevice::UNKNOWN_MIDI;

                    sdev = midiDevices.find(act->text(), typ);
                    delete pup;

                    // Is it the current device? Reset it to <none>.
                    // falkTX, handle synths properly here
                    if (sdev == dev)
                    {
                        sdev = 0;
                    }
                    else
                    {
                    }
                }

                midiSeq->msgSetMidiDevice(port, sdev);
                los->changeConfig(true); // save configuration file
                song->update();
            }
        }
            //break;
            return;

        case DEVCOL_INSTR:
        {
            if (instrPopup == 0)
                instrPopup = new QMenu(this);
            instrPopup->clear();
            for (iMidiInstrument i = midiInstruments.begin(); i != midiInstruments.end(); ++i)
            {
                instrPopup->addAction((*i)->iname());
            }

            QAction* act = instrPopup->exec(ppt, 0);
            if (!act)
                return;
            QString s = act->text();
            item->tableWidget()->item(item->row(), DEVCOL_INSTR)->setText(s);
            for (iMidiInstrument i = midiInstruments.begin(); i != midiInstruments.end(); ++i)
            {
                if ((*i)->iname() == s)
                {
                    port->setInstrument(*i);
                    break;
                }
            }
            song->update();
        }
            return;
    }
}
Esempio n. 7
0
File: midi.cpp Progetto: faesong/oom
void Audio::processMidi()
{
	midiBusy = true;
	//
	// TODO: syntis should directly write into recordEventList
	//
	for (iMidiDevice id = midiDevices.begin(); id != midiDevices.end(); ++id)
	{
		MidiDevice* md = *id;

		MPEventList* playEvents = md->playEvents();
		//
		// erase already played events:
		//
		iMPEvent nextPlayEvent = md->nextPlayEvent();
		playEvents->erase(playEvents->begin(), nextPlayEvent);

		// klumsy hack for synti devices:
		if (md->isSynti())
		{
			SynthI* s = (SynthI*) md;
			while (s->eventsPending())
			{
				MidiRecordEvent ev = s->receiveEvent();
				md->recordEvent(ev);
			}
		}

		// Is it a Jack midi device?
		//MidiJackDevice* mjd = dynamic_cast<MidiJackDevice*>(md);
		//if(mjd)
		//  mjd->collectMidiEvents();
		md->collectMidiEvents();

		// Take snapshots of the current sizes of the recording fifos,
		//  because they may change while here in process, asynchronously.
		md->beforeProcess();
	}

	MPEventList* playEvents = metronome->playEvents();
	iMPEvent nextPlayEvent = metronome->nextPlayEvent();
	playEvents->erase(playEvents->begin(), nextPlayEvent);

	// p3.3.25
	bool extsync = extSyncFlag.value();

	for (iMidiTrack t = song->midis()->begin(); t != song->midis()->end(); ++t)
	{
		MidiTrack* track = *t;
		int port = track->outPort();
		MidiDevice* md = midiPorts[port].device();

		// Changed by Tim. p3.3.8
		//if(md == 0)
		//  continue;
		//MPEventList* playEvents = md->playEvents();
		//if (playEvents == 0)
		//    continue;
		//if (!track->isMute())
		MPEventList* playEvents = 0;
		if (md)
		{
			playEvents = md->playEvents();

			// only add track events if the track is unmuted
			if (!track->isMute())
			{
				if (isPlaying() && (curTickPos < nextTickPos))
					collectEvents(track, curTickPos, nextTickPos);
			}
		}

		//
		//----------midi recording
		//
		if (track->recordFlag())
		{
			//int portMask    = track->inPortMask();
			// p3.3.38 Removed
			//unsigned int portMask = track->inPortMask();
			//int channelMask = track->inChannelMask();

			MPEventList* rl = track->mpevents();
			MidiPort* tport = &midiPorts[port];

			// p3.3.38
			//for (iMidiDevice id = midiDevices.begin(); id != midiDevices.end(); ++id)
			//{
			RouteList* irl = track->inRoutes();
			for (ciRoute r = irl->begin(); r != irl->end(); ++r)
			{
				//if(!r->isValid() || (r->type != Route::ALSA_MIDI_ROUTE && r->type != Route::JACK_MIDI_ROUTE))
				//if(!r->isValid() || (r->type != Route::MIDI_DEVICE_ROUTE))
				if (!r->isValid() || (r->type != Route::MIDI_PORT_ROUTE)) // p3.3.49
					continue;

				int devport = r->midiPort; // p3.3.49
				if (devport == -1)
					continue;

				//MidiDevice* dev = *id;
				//MidiDevice* dev = r->device;
				MidiDevice* dev = midiPorts[devport].device(); // p3.3.49
				if (!dev)
					continue;


				// p3.3.50 Removed
				//int channel = r->channel;
				// NOTE: TODO: Special for input device sysex 'channel' marked as -1, ** IF we end up going with that method **.
				// This would mean having a separate 'System' channel listed in the routing popups.
				// The other alternative is to accept sysex from a device as long as ANY regular channel is routed from it,
				//  this does not require a 'System' channel listed in the routing popups.
				// But that requires more code below... Done.
				//if(channel == -1)
				//channel = MIDI_CHANNELS; // Special channel '17'
				//  continue;

				//int devport = dev->midiPort();

				// record only from ports marked in portMask:
				//if (devport == -1 || !(portMask & (1 << devport)))
				//if (devport == -1)
				//      continue;

				//MREventList* el = dev->recordEvents();
				//MidiFifo& rf = dev->recordEvents();


				int channelMask = r->channel; // p3.3.50
				if (channelMask == -1 || channelMask == 0)
					continue;
				for (int channel = 0; channel < MIDI_CHANNELS; ++channel) // p3.3.50
				{
					if (!(channelMask & (1 << channel)))
						continue;

					if (!dev->sysexFIFOProcessed())
					{
						// Set to the sysex fifo at first.
						MidiFifo& rf = dev->recordEvents(MIDI_CHANNELS);
						// Get the frozen snapshot of the size.
						int count = dev->tmpRecordCount(MIDI_CHANNELS);

						for (int i = 0; i < count; ++i)
						{
							MidiPlayEvent event(rf.peek(i));

							//unsigned time = event.time() + segmentSize*(segmentCount-1);
							//unsigned time = event.time() + (extsync ? config.division/24 : segmentSize*(segmentCount-1));
							//unsigned time = extsync ? curTickPos : (event.time() + segmentSize*(segmentCount-1));
							//event.setTime(time);
							//if(!extsync)
							//  event.setTime(event.time() + segmentSize*(segmentCount-1));

							event.setPort(port);

							// dont't echo controller changes back to software
							// synthesizer:
							if (!dev->isSynti() && md && track->recEcho())
								playEvents->add(event);

							// If syncing externally the event time is already in units of ticks, set above.
							if (!extsync)
							{
								//time = tempomap.frame2tick(event.time());
								//event.setTime(time);  // set tick time
								event.setTime(tempomap.frame2tick(event.time())); // set tick time
							}

							if (recording)
								rl->add(event);
						}

						dev->setSysexFIFOProcessed(true);
					}

					// Set to the sysex fifo at first.
					///MidiFifo& rf = dev->recordEvents(MIDI_CHANNELS);
					// Get the frozen snapshot of the size.
					///int count = dev->tmpRecordCount(MIDI_CHANNELS);

					// Iterate once for sysex fifo (if needed), once for channel fifos.
					///for(int sei = 0; sei < 2; ++sei)
					{
						// If on first pass, do sysex fifo.
						/*
						if(sei == 0)
						{
						  // Ignore any further channel routes on this device if already done here.
						  if(dev->sysexFIFOProcessed())
							continue;
						  // Go ahead and set this now.
						  dev->setSysexFIFOProcessed(true);
						  // Allow it to fall through with the sysex fifo and count...
						}
						else
						{
						  // We're on the second pass, do channel fifos.
						  rf = dev->recordEvents(channel);
						  // Get the frozen snapshot of the size.
						  count = dev->tmpRecordCount(channel);
						}
						 */

						MidiFifo& rf = dev->recordEvents(channel);
						int count = dev->tmpRecordCount(channel);

						//for (iMREvent ie = el->begin(); ie != el->end(); ++ie)
						for (int i = 0; i < count; ++i)
						{
							MidiPlayEvent event(rf.peek(i));

							//int channel = ie->channel();
							///int channel = event.channel();

							int defaultPort = devport;
							///if (!(channelMask & (1 << channel)))
							///{
							///      continue;
							///}

							//MidiPlayEvent event(*ie);
							int drumRecPitch = 0; //prevent compiler warning: variable used without initialization
							MidiController *mc = 0;
							int ctl = 0;

							//Hmmm, hehhh...
							// TODO: Clean up a bit around here when it comes to separate events for rec & for playback.
							// But not before 0.7 (ml)

							int prePitch = 0, preVelo = 0;

							event.setChannel(track->outChannel());

							if (event.isNote() || event.isNoteOff())
							{
								//
								// apply track values
								//

								//Apply drum inkey:
								if (track->type() == Track::DRUM)
								{
									int pitch = event.dataA();
									//Map note that is played according to drumInmap
									drumRecPitch = drumMap[(unsigned int) drumInmap[pitch]].enote;
									devport = drumMap[(unsigned int) drumInmap[pitch]].port;
									event.setPort(devport);
									channel = drumMap[(unsigned int) drumInmap[pitch]].channel;
									event.setA(drumMap[(unsigned int) drumInmap[pitch]].anote);
									event.setChannel(channel);
								}
								else
								{ //Track transpose if non-drum
									prePitch = event.dataA();
									int pitch = prePitch + track->transposition;
									if (pitch > 127)
										pitch = 127;
									if (pitch < 0)
										pitch = 0;
									event.setA(pitch);
								}

								if (!event.isNoteOff())
								{
									preVelo = event.dataB();
									int velo = preVelo + track->velocity;
									velo = (velo * track->compression) / 100;
									if (velo > 127)
										velo = 127;
									if (velo < 1)
										velo = 1;
									event.setB(velo);
								}
							}
								// Added by T356.
							else if (event.type() == ME_CONTROLLER)
							{
								//printf("11111111111111111111111111111111111111111111111111111\n");
								if (track->type() == Track::DRUM)
								{
									//printf("2222222222222222222222222222222222222222222222222222222222\n");
									ctl = event.dataA();
									// Regardless of what port the event came from, is it a drum controller event
									//  according to the track port's instrument?
									mc = tport->drumController(ctl);
									if (mc)
									{

										//printf("333333333333333333333333333333333333333333333333\n");
										int pitch = ctl & 0x7f;
										ctl &= ~0xff;
										int dmindex = drumInmap[pitch] & 0x7f;
										//Map note that is played according to drumInmap
										drumRecPitch = drumMap[dmindex].enote;
										devport = drumMap[dmindex].port;
										event.setPort(devport);
										channel = drumMap[dmindex].channel;
										event.setA(ctl | drumMap[dmindex].anote);
										event.setChannel(channel);
									}
								}
							}

							// p3.3.25
							// OOMidi uses a fixed clocks per quarternote of 24.
							// At standard 384 ticks per quarternote for example,
							// 384/24=16 for a division of 16 sub-frames (16 OOMidi 'ticks').
							// That is what we'll use if syncing externally.
							//unsigned time = event.time() + segmentSize*(segmentCount-1);
							//unsigned time = event.time() + (extsync ? config.division/24 : segmentSize*(segmentCount-1));
							// p3.3.34
							// Oops, use the current tick.
							//unsigned time = extsync ? curTickPos : (event.time() + segmentSize*(segmentCount-1));
							//event.setTime(time);
							// p3.3.35
							// If ext sync, events are now time-stamped with last tick in MidiDevice::recordEvent().
							// TODO: Tested, but record resolution not so good. Switch to wall clock based separate list in MidiDevice.
							// p3.3.36
							//if(!extsync)
							//  event.setTime(event.time() + segmentSize*(segmentCount-1));

							// dont't echo controller changes back to software
							// synthesizer:

							if (!dev->isSynti())
							{
								//printf("444444444444444444444444444444444444444444444444444444\n");
								//Check if we're outputting to another port than default:
								if (devport == defaultPort)
								{

									//printf("5555555555555555555555555555555555555555555\n");
									event.setPort(port);
									if (md && track->recEcho())
										playEvents->add(event);
								}
								else
								{
									//printf("66666666666666666666666666666666666666\n");
									// Hmm, this appears to work, but... Will this induce trouble with md->setNextPlayEvent??
									MidiDevice* mdAlt = midiPorts[devport].device();
									if (mdAlt && track->recEcho())
										mdAlt->playEvents()->add(event);
								}
								// Shall we activate meters even while rec echo is off? Sure, why not...
								if (event.isNote() && event.dataB() > track->activity())
									track->setActivity(event.dataB());
							}

							// p3.3.25
							// If syncing externally the event time is already in units of ticks, set above.
							if (!extsync)
							{
								//printf("7777777777777777777777777777777777777777777\n");
								// p3.3.35
								//time = tempomap.frame2tick(event.time());
								//event.setTime(time);  // set tick time
								event.setTime(tempomap.frame2tick(event.time())); // set tick time
							}

							// Special handling of events stored in rec-lists. a bit hACKish. TODO: Clean up (after 0.7)! :-/ (ml)
							if (recording)
							{
								//printf("888888888888888888888888888888888888888888888888\n");
								// In these next steps, it is essential to set the recorded event's port
								//  to the track port so buildMidiEventList will accept it. Even though
								//  the port may have no device "<none>".
								//
								if (track->type() == Track::DRUM)
								{
									//printf("99999999999999999999999999999999999999999999999999\n");
									// Is it a drum controller event?
									if (mc)
									{
										//printf("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n");
										MidiPlayEvent drumRecEvent = event;
										drumRecEvent.setA(ctl | drumRecPitch);
										// In this case, preVelo is simply the controller value.
										drumRecEvent.setB(preVelo);
										drumRecEvent.setPort(port); //rec-event to current port
										drumRecEvent.setChannel(track->outChannel()); //rec-event to current channel
										rl->add(drumRecEvent);
									}
									else
									{
										//printf("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n");

										MidiPlayEvent drumRecEvent = event;
										drumRecEvent.setA(drumRecPitch);
										drumRecEvent.setB(preVelo);
										// Changed by T356.
										// Tested: Events were not being recorded for a drum map entry pointing to a
										//  different port. This must have been wrong - buildMidiEventList would ignore this.
										//drumRecEvent.setPort(devport);
										drumRecEvent.setPort(port); //rec-event to current port

										drumRecEvent.setChannel(track->outChannel()); //rec-event to current channel
										rl->add(drumRecEvent);
									}
								}
								else
								{
									//printf("ccccccccccccccccccccccccccccccccccccccccccccc\n");
									// Restore record-pitch to non-transposed value since we don't want the note transposed twice next
									MidiPlayEvent recEvent = event;
									if (prePitch)
										recEvent.setA(prePitch);
									if (preVelo)
										recEvent.setB(preVelo);
									recEvent.setPort(port);
									recEvent.setChannel(track->outChannel());

									rl->add(recEvent);
								}
							}
						}
					}
				}
			}
		}
		// Added by Tim. p3.3.8
		if (md)
		{
			//printf("zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz\n");

			md->setNextPlayEvent(playEvents->begin());
		}
	}

	//
	// clear all recorded events in midiDevices
	// process stuck notes
	//
	for (iMidiDevice id = midiDevices.begin(); id != midiDevices.end(); ++id)
	{
		//printf("--------------------------aaaaaaaaaaaaaaaaaaaaaaaaaaaa\n");
		MidiDevice* md = *id;

		///md->recordEvents()->clear();
		// By T356. Done processing this rec buffer, now flip to the other one.
		///md->flipRecBuffer();
		// We are done with the 'frozen' recording fifos, remove the events.
		md->afterProcess();

		MPEventList* stuckNotes = md->stuckNotes();
		MPEventList* playEvents = md->playEvents();

		iMPEvent k;
		for (k = stuckNotes->begin(); k != stuckNotes->end(); ++k)
		{
			if (k->time() >= nextTickPos)
				break;
			MidiPlayEvent ev(*k);

			// p3.3.25
			//int frame = tempomap.tick2frame(k->time()) + frameOffset;
			if (extsync)
			{
				ev.setTime(k->time());
			}
			else
			{
				int frame = tempomap.tick2frame(k->time()) + frameOffset;
				ev.setTime(frame);
			}

			// p3.3.25
			//ev.setTime(frame);

			playEvents->add(ev);
		}
		stuckNotes->erase(stuckNotes->begin(), k);
		md->setNextPlayEvent(playEvents->begin());
	}

	//---------------------------------------------------
	//    insert metronome clicks
	//---------------------------------------------------

	MidiDevice* md = 0;
	if (midiClickFlag)
		md = midiPorts[clickPort].device();
	if (song->click() && (isPlaying() || state == PRECOUNT))
	{
		MPEventList* playEvents = 0;
		MPEventList* stuckNotes = 0;
		if (md)
		{
			playEvents = md->playEvents();
			stuckNotes = md->stuckNotes();
		}
		int bar, beat;
		unsigned tick;
		bool isMeasure = false;
		while (midiClick < nextTickPos)
		{
			if (isPlaying())
			{
				///sigmap.tickValues(midiClick, &bar, &beat, &tick);
				AL::sigmap.tickValues(midiClick, &bar, &beat, &tick);
				isMeasure = beat == 0;
			}
			else if (state == PRECOUNT)
			{
				isMeasure = (clickno % clicksMeasure) == 0;
			}
			// p3.3.25
			//int frame = tempomap.tick2frame(midiClick) + frameOffset;
			int evtime = extsync ? midiClick : tempomap.tick2frame(midiClick) + frameOffset;

			// p3.3.25
			//MidiPlayEvent ev(frame, clickPort, clickChan, ME_NOTEON,
			MidiPlayEvent ev(evtime, clickPort, clickChan, ME_NOTEON,
					beatClickNote, beatClickVelo);

			if (md)
			{
				// p3.3.25
				//MidiPlayEvent ev(frame, clickPort, clickChan, ME_NOTEON,
				MidiPlayEvent ev(evtime, clickPort, clickChan, ME_NOTEON,
						beatClickNote, beatClickVelo);

				if (isMeasure)
				{
					ev.setA(measureClickNote);
					ev.setB(measureClickVelo);
				}
				playEvents->add(ev);
			}
			if (audioClickFlag)
			{
				// p3.3.25
				//MidiPlayEvent ev1(frame, 0, 0, ME_NOTEON, 0, 0);
				MidiPlayEvent ev1(evtime, 0, 0, ME_NOTEON, 0, 0);

				ev1.setA(isMeasure ? 0 : 1);
				metronome->playEvents()->add(ev1);
			}
			if (md)
			{
				ev.setB(0);
				// p3.3.25
				// Removed. Why was this here?
				//frame = tempomap.tick2frame(midiClick+20) + frameOffset;
				//
				// Does it mean this should be changed too?
				// No, stuck notes are in units of ticks, not frames like (normal, non-external) play events...
				ev.setTime(midiClick + 10);

				if (md)
					stuckNotes->add(ev);
			}

			if (isPlaying())
				///midiClick = sigmap.bar2tick(bar, beat+1, 0);
				midiClick = AL::sigmap.bar2tick(bar, beat + 1, 0);
			else if (state == PRECOUNT)
			{
				midiClick += ticksBeat;
				if (clickno)
					--clickno;
				else
					state = START_PLAY;
			}
		}
		if (md)
			md->setNextPlayEvent(playEvents->begin());
		if (audioClickFlag)
			metronome->setNextPlayEvent(metronome->playEvents()->begin());
	}

	if (state == STOP)
	{
		//---------------------------------------------------
		//    end all notes
		//---------------------------------------------------

		for (iMidiDevice imd = midiDevices.begin(); imd != midiDevices.end(); ++imd)
		{
			MidiDevice* md = *imd;
			MPEventList* playEvents = md->playEvents();
			MPEventList* stuckNotes = md->stuckNotes();
			for (iMPEvent k = stuckNotes->begin(); k != stuckNotes->end(); ++k)
			{
				MidiPlayEvent ev(*k);
				ev.setTime(0); // play now
				playEvents->add(ev);
			}
			stuckNotes->clear();
		}
	}


	// p3.3.36
	//int tickpos = audio->tickPos();
	//bool extsync = extSyncFlag.value();
	//
	// Special for Jack midi devices: Play all Jack midi events up to curFrame.
	//
	for (iMidiDevice id = midiDevices.begin(); id != midiDevices.end(); ++id)
	{
		(*id)->processMidi();

		/*
		int port = md->midiPort();
		MidiPort* mp = port != -1 ? &midiPorts[port] : 0;
		MPEventList* el = md->playEvents();
		if (el->empty())
			  continue;
		iMPEvent i = md->nextPlayEvent();
		for(; i != el->end(); ++i)
		{
		  // If syncing to external midi sync, we cannot use the tempo map.
		  // Therefore we cannot get sub-tick resolution. Just use ticks instead of frames.
		  //if(i->time() > curFrame)
		  if(i->time() > (extsync ? tickpos : curFrame))
		  {
			//printf("  curT %d  frame %d\n", i->time(), curFrame);
			break; // skip this event
		  }

		  if(mp)
		  {
			if(mp->sendEvent(*i))
			  break;
		  }
		  else
		  {
			if(md->putEvent(*i))
			  break;
		  }
		}
		md->setNextPlayEvent(i);
		 */
	}

	midiBusy = false;
}
Esempio n. 8
0
void AudioPortConfig::addOutRoute()/*{{{*/
{
    QListWidgetItem* dstItem = newDstList->currentItem();
    QListWidgetItem* tItem = tracksList->currentItem();
    if (!_selected || dstItem == 0)
        return;

    RouteList* rl = _selected->outRoutes();
    int chan = 0;

    if (_selected->type() == Track::WAVE_OUTPUT_HELPER)
    {
        if(!tItem)
            return;
        int row = tracksList->row(tItem);
        QList<QListWidgetItem*> found = tracksList->findItems(tItem->text(), Qt::MatchExactly);
        if(found.isEmpty())
            return;
        for(int i = 0; i < found.size(); ++i)
        {
            QListWidgetItem* item = found.at(i);
            chan = i;
            int r = tracksList->row(item);
            if(r == row)
                break;
        }

        Route srcRoute(_selected, chan);
        Route dstRoute(dstItem->text(), true, -1, Route::JACK_ROUTE);
        dstRoute.channel = chan;

        // check if route src->dst exists:
        iRoute irl = rl->begin();
        for (; irl != rl->end(); ++irl)
        {
            if (*irl == dstRoute)
                break;
        }
        audio->msgAddRoute(srcRoute, dstRoute);
        audio->msgUpdateSoloStates();
        song->update(SC_ROUTE);
        //new QTreeWidgetItem(routeList, QStringList() << srcRoute.name() << dstRoute.name());
        btnConnectOut->setEnabled(false);
        return;
    }
    else
    {
        Route srcRoute(_selected, chan, _selected->channels());
        Route dstRoute(dstItem->text(), true, -1);

        audio->msgAddRoute(srcRoute, dstRoute);
        audio->msgUpdateSoloStates();
        song->update(SC_ROUTE);
        //new QTreeWidgetItem(routeList, QStringList() << srcRoute.name() << dstRoute.name());
        btnConnectOut->setEnabled(false);
    }
    /*
    audio->msgAddRoute(Route(srcItem->text(), false, -1), Route(dstItem->text(), true, -1));
    audio->msgUpdateSoloStates();
    //song->update(SC_SOLO);
    song->update(SC_ROUTE);
    new QTreeWidgetItem(routeList, QStringList() << srcItem->text() << dstItem->text());
    connectButton->setEnabled(false);
    */
}/*}}}*/