When the instrument is changed a new sequencer object is obtained, you need to add the listener again:
B4X:private Sub SelezionaMidiOut ' Per cambiare il midi out If Seqr.IsInitialized Then Seqr.Stop ResetDevices Dim Md() As MidiDeviceInfo= MidiSystemStatic.GetMidiDeviceInfo MidiDev = MidiSystemStatic.GetMidiDevice(Md(ChoiceDevice.SelectedIndex)) MidiDev.Open Dim midioutrec As MidiReceiver = MidiDev.GetReceiver Dim Seqr As MidiSequencer = MidiSystemStatic.GetSequencer2(False) Seqr.GetTransmitter.SetReceiver(midioutrec) Seqr.Open Seqr.AddMetaEventListener(Me,"Meta") 'Add the meta listener to the new sequencer instance. If Seq.IsInitialized Then Seqr.SetSequence2(Seq) End Sub
Here:you need to do something similar for the program change
Private Sub CambiaStrumento (NrTraccia As Int, NrStrumento As Int)
Dim Tick As Long = Seqr.GetTickPosition
If Synth.IsInitialized Then
NrTraccia = NrTraccia-1
Dim Chnls() As MidiChannel = Synth.GetChannels
Chnls(NrTraccia).ProgramChange(NrStrumento)
Else
Dim chnl As Int = GetTrackChannel(Seq.GetTracks(NrTraccia))
If chnl > -1 Then
Dim mm As MidiShortMessage = MidiMessageBuilder.ProgramChange(chnl,NrStrumento,-1)
MidiDev.GetReceiver.Send(mm,-1)
End If
End If
If Seqr.IsRunning Then
Dim T As MidiTrack = Seq.GetTracks(NrTraccia)
Dim chnl As Int = GetTrackChannel(T)
If chnl > -1 Then
Dim mm As MidiShortMessage = MidiMessageBuilder.ProgramChange(chnl,NrStrumento,Tick)
Dim PCEvt As MidiEvent
PCEvt.Initialize
PCEvt.CreateShort(mm, Tick)
T.Add(PCEvt)
End If
End If
End Sub
Private Sub GetTrackChannel(TTrack As MidiTrack) As Int
For i = 0 To TTrack.Size - 1
Dim Mevt As MidiEvent = TTrack.Get(i)
If Mevt.GetMessage.IsShortMessage Then
Return Mevt.GetMessage.AsShortMessage.GetChannel
End If
Next
Return -1
End Sub
If you mute the track that has lyrics on then the meta messages won't be sent. You can't control an external device with the synth object.mute / solo ... and it doesn't always happen.
Did you look at the MidiSynthesizer class? Use GetAvailableInstruments, which returns a list of MidiInstruments ThenRetrieve the instrument list in the synth after loading the soundfont.
For Each MI as MidiInstrument In Synth.GetAvailableInstruments
Log(MI.Name)
Next
Why Not?2) Use midi devices well, I can't do what you kindly described to me
As I said before, you can't control an external instrument using a synth object, unless the MidiDevice is recognised as a Synthesizer. You can check it with MidiDevice.IsSynthesizer. This is only likely to work if the external instrument is connected via USB (Not a midi port adapter), even then there is no guarantee.3) I wanted to leave the synth for managing the mute / solo. So I avoid further complications.
Thanks.Did you look at the MidiSynthesizer class? Use GetAvailableInstruments, which returns a list of MidiInstruments Then
B4X:For Each MI as MidiInstrument In Synth.GetAvailableInstruments Log(MI.Name) Next
Attached external instruments (Unless they are a synthesizer see answer to 3) will not return an instrument list using this method. It is possible that it may respond to a Sysex command to get a dump of the patches which you would then need to parse.
Why Not?
As I said before, you can't control an external instrument using a synth object, unless the MidiDevice is recognised as a Synthesizer. You can check it with MidiDevice.IsSynthesizer. This is only likely to work if the external instrument is connected via USB (Not a midi port adapter), even then there is no guarantee.
Yes.Thanks for reporting this. fixed for next release of library.
It would have crashed the app though and not returned empty instruments.
Is it working for you now?