All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.leovr.rtipmidi.MidiDeviceAppleMidiSession Maven / Gradle / Ivy

The newest version!
package io.github.leovr.rtipmidi;

import io.github.leovr.rtipmidi.error.AppleMidiSessionInstantiationException;
import io.github.leovr.rtipmidi.session.AppleMidiSession;

import javax.annotation.Nonnull;
import javax.sound.midi.MidiDevice;
import javax.sound.midi.MidiMessage;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.Receiver;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

/**
 * {@link AppleMidiSession} with one or more {@link MidiDevice} as the receiver or sender of the MIDI messages
 */
public class MidiDeviceAppleMidiSession extends JavaxAppleMidiSession {

    private final List midiDevices = new ArrayList<>();
    private List receivers = new ArrayList<>();

    public MidiDeviceAppleMidiSession(@Nonnull final MidiDeviceModePair midiDeviceModePair) {
        this(Collections.singletonList(midiDeviceModePair));
    }

    public MidiDeviceAppleMidiSession(final Collection midiDeviceModePairs) {
        for (final MidiDeviceModePair pair : midiDeviceModePairs) {
            final MidiDevice device = pair.getDevice();
            final MidiDeviceMode mode = pair.getMode();

            openMidiDevice(device);

            initReading(device, mode);
            initWriting(device, mode);

            midiDevices.add(device);
        }
    }

    private void initWriting(final @Nonnull MidiDevice midiDevice, final @Nonnull MidiDeviceMode deviceMode) {
        if (deviceMode == MidiDeviceMode.BIDIRECTIONAL || deviceMode == MidiDeviceMode.WRITE_ONLY) {
            if (midiDevice.getMaxTransmitters() == 0) {
                throw new AppleMidiSessionInstantiationException(
                        "MIDI-Device cannot have any more transmitters or does not support transmitters");
            }
            try {
                midiDevice.getTransmitter().setReceiver(new MidiDeviceReceiver());
            } catch (final MidiUnavailableException e) {
                throw new AppleMidiSessionInstantiationException("Error getting transmitter", e);
            }
        }
    }

    private void initReading(final @Nonnull MidiDevice midiDevice, final @Nonnull MidiDeviceMode deviceMode) {
        if (deviceMode == MidiDeviceMode.BIDIRECTIONAL || deviceMode == MidiDeviceMode.READ_ONLY) {
            if (midiDevice.getMaxReceivers() == 0) {
                throw new AppleMidiSessionInstantiationException(
                        "MIDI-Device cannot have any more receivers or does not support receivers");
            }
            try {
                receivers.add(midiDevice.getReceiver());
            } catch (final MidiUnavailableException e) {
                throw new AppleMidiSessionInstantiationException("Error getting receiver", e);
            }
        }
    }

    private void openMidiDevice(final @Nonnull MidiDevice midiDevice) {
        if (midiDevice.isOpen()) {
            throw new AppleMidiSessionInstantiationException("MIDI-Device is already open");
        }
        try {
            midiDevice.open();
        } catch (final MidiUnavailableException e) {
            throw new AppleMidiSessionInstantiationException("Error opening MIDI device", e);
        }
    }

    @Override
    protected void onMidiMessage(final MidiMessage message, final long timestamp) {
        if (receivers.isEmpty()) {
            return;
        }
        for (final Receiver receiver : receivers) {
            receiver.send(message, timestamp);
        }
    }

    @Override
    public long getCurrentTimestamp() {
        for (final MidiDevice device : midiDevices) {
            final long microsecondPosition = device.getMicrosecondPosition();
            if (microsecondPosition != -1) {
                return timestampOffset + microsecondPosition / 100;
            }
        }
        return -1;
    }

    @Override
    protected void onEndSession() {
        for (final MidiDevice device : midiDevices) {
            device.close();
        }
    }

    private class MidiDeviceReceiver implements Receiver {

        @Override
        public void send(final MidiMessage message, final long timeStamp) {
            sendMidiMessage(message, timeStamp);
        }

        @Override
        public void close() {
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy