--- linuxsampler/trunk/src/engines/gig/Engine.cpp 2008/06/22 14:46:46 1748 +++ linuxsampler/trunk/src/engines/gig/Engine.cpp 2008/11/01 19:01:27 1789 @@ -291,7 +291,7 @@ // make sure that the engine does not get any sysex messages // while it's reseting bool sysexDisabled = MidiInputPort::RemoveSysexListener(this); - ActiveVoiceCount = 0; + SetVoiceCount(0); ActiveVoiceCountMax = 0; // reset voice stealing parameters @@ -573,6 +573,7 @@ // return if engine disabled if (EngineDisabled.Pop()) { dmsg(5,("gig::Engine: engine disabled (val=%d)\n",EngineDisabled.GetUnsafe())); + EngineDisabled.RttDone(); return 0; } @@ -685,8 +686,8 @@ pVoiceStealingQueue->clear(); // just some statistics about this engine instance - ActiveVoiceCount = ActiveVoiceCountTemp; - if (ActiveVoiceCount > ActiveVoiceCountMax) ActiveVoiceCountMax = ActiveVoiceCount; + SetVoiceCount(ActiveVoiceCountTemp); + if (VoiceCount() > ActiveVoiceCountMax) ActiveVoiceCountMax = VoiceCount(); // in case regions were previously suspended and we killed voices // with disk streams due to that, check if those streams have finally @@ -698,6 +699,7 @@ } FrameTime += Samples; + EngineDisabled.RttDone(); return 0; } @@ -784,7 +786,7 @@ voiceCount++; if (itVoice->PlaybackState == Voice::playback_state_disk) { - if ((itVoice->DiskStreamRef).State == Stream::state_active) streamCount++; + if ((itVoice->DiskStreamRef).State != Stream::state_unused) streamCount++; } } else { // voice reached end, is now inactive FreeVoice(pEngineChannel, itVoice); // remove voice from the list of active voices @@ -825,7 +827,7 @@ pEngineChannel->SetVoiceCount(pEngineChannel->GetVoiceCount() + 1); if (itNewVoice->PlaybackState == Voice::playback_state_disk) { - if (itNewVoice->DiskStreamRef.State == Stream::state_active) { + if (itNewVoice->DiskStreamRef.State != Stream::state_unused) { pEngineChannel->SetDiskStreamCount(pEngineChannel->GetDiskStreamCount() + 1); } } @@ -953,12 +955,15 @@ * * @param pData - pointer to sysex data * @param Size - lenght of sysex data (in bytes) + * @param pSender - the MIDI input port on which the SysEx message was + * received */ - void Engine::SendSysex(void* pData, uint Size) { + void Engine::SendSysex(void* pData, uint Size, MidiInputPort* pSender) { Event event = pEventGenerator->CreateEvent(); event.Type = Event::type_sysex; event.Param.Sysex.Size = Size; event.pEngineChannel = NULL; // as Engine global event + event.pMidiInputPort = pSender; if (pEventQueue->write_space() > 0) { if (pSysexBuffer->write_space() >= Size) { // copy sysex data to input buffer @@ -1901,10 +1906,27 @@ switch (sub_id1) { case 0x04: // Device Control switch (sub_id2) { - case 0x01: // Master Volume - GLOBAL_VOLUME = + case 0x01: { // Master Volume + const double volume = double((uint(val_msb)<<7) | uint(val_lsb)) / 16383.0; + #if CONFIG_MASTER_VOLUME_SYSEX_BY_PORT + // apply volume to all sampler channels that + // are connected to the same MIDI input port + // this sysex message arrived on + for (int i = 0; i < engineChannels.size(); ++i) { + EngineChannel* pEngineChannel = engineChannels[i]; + if (pEngineChannel->GetMidiInputPort() == + itSysexEvent->pMidiInputPort) + { + pEngineChannel->Volume(volume); + } + } + #else + // apply volume globally to the whole sampler + GLOBAL_VOLUME = volume; + #endif // CONFIG_MASTER_VOLUME_SYSEX_BY_PORT break; + } } break; } @@ -1946,6 +1968,32 @@ dmsg(3,("\t\t\tNew scale applied.\n")); break; } + case 0x15: { // chromatic / drumkit mode + dmsg(3,("\t\tMIDI Instrument Map Switch\n")); + uint8_t part = addr[1] & 0x0f; + uint8_t map; + if (!reader.pop(&map)) goto free_sysex_data; + for (int i = 0; i < engineChannels.size(); ++i) { + EngineChannel* pEngineChannel = engineChannels[i]; + if ( + (pEngineChannel->midiChannel == part || + pEngineChannel->midiChannel == midi_chan_all) && + pEngineChannel->GetMidiInputPort() == itSysexEvent->pMidiInputPort + ) { + try { + pEngineChannel->SetMidiInstrumentMap(map); + } catch (Exception e) { + dmsg(2,("\t\t\tCould not apply MIDI instrument map %d to part %d: %s\n", map, part, e.Message().c_str())); + goto free_sysex_data; + } catch (...) { + dmsg(2,("\t\t\tCould not apply MIDI instrument map %d to part %d (unknown exception)\n", map, part)); + goto free_sysex_data; + } + } + } + dmsg(3,("\t\t\tApplied MIDI instrument map %d to part %d.\n", map, part)); + break; + } } } else if (addr[0] == 0x40 && (addr[1] & 0xf0) == 0x20) { // Part Parameters (2) @@ -2052,7 +2100,11 @@ } uint Engine::VoiceCount() { - return ActiveVoiceCount; + return atomic_read(&ActiveVoiceCount); + } + + void Engine::SetVoiceCount(uint Count) { + atomic_set(&ActiveVoiceCount, Count); } uint Engine::VoiceCountMax() { @@ -2064,7 +2116,7 @@ } uint Engine::DiskStreamCount() { - return (pDiskThread) ? pDiskThread->ActiveStreamCount : 0; + return (pDiskThread) ? pDiskThread->GetActiveStreamCount() : 0; } uint Engine::DiskStreamCountMax() { @@ -2088,7 +2140,7 @@ } String Engine::Version() { - String s = "$Revision: 1.93 $"; + String s = "$Revision: 1.98 $"; return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword }