0

私は midi プログラムに取り組んでおり、使用する代わりに多数の MIDI シーケンサーを使用する場合に、ユーザーがどの MIDI シーケンサーを使用するかを選択できるようにしたいと考えていますMidiSystem.getSequencer()

編集

私のコードは次のようになります。

public class Demo {

  public static void main(String[] args) {
    Sequencer sequencer;

    //Gets default sequencer if only one argument given
    try {
      sequencer = MidiSystem.getSequencer();
    } catch (MidiUnavailableException e) {
      e.printStackTrace();
      return;
    }

    if (args.length == 0) {
      return;
    }

    File file = new File(args[0]);

    boolean select = args.length > 1;

    MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
    List<String> sequencers = new ArrayList<>();
    MidiDevice device;

    //Populates sequencers lists with potential values and prints
    for (int i = 0; i < infos.length; i++) {
      try {
        device = MidiSystem.getMidiDevice(infos[i]);
        if (device instanceof Sequencer) {
          System.out.println(sequencers.size() + ": " + device.getDeviceInfo().getName());
          sequencers.add(device.getDeviceInfo().getName());
        }
      } catch (MidiUnavailableException e) {
        System.out.println(e.getMessage());
      }
    }

    String name;

    //If multiple arguments are given select a new sequencer from the list
    if (select) {
      Scanner scanner = new Scanner(System.in);
      System.out.println("Enter the number of the sequencer you wish to use");
      name = sequencers.get(scanner.nextInt());

      for (int i = 0; i < infos.length; i++) {
        try {
          device = MidiSystem.getMidiDevice(infos[i]);

          if (device.getDeviceInfo().getName().equals(name)) {
            //TODO: This line does not create a valid sequencer
            sequencer = (Sequencer) device;
            System.out.println("Sequencer changed to " + device.getDeviceInfo().getName());
          }
        } catch (MidiUnavailableException e) {
          System.out.println("Cannot locate device " + name);
        }
      }
    }

    //Attempt to play midi data from a file into selected sequencer
    if (sequencer != null) {
      if (!sequencer.isOpen()) {
        try {
          sequencer.open();
        } catch (MidiUnavailableException e) {
          e.printStackTrace();
        }
      }
      try {
        sequencer.setSequence(MidiSystem.getSequence(file));
      } catch (InvalidMidiDataException | IOException e) {
        e.printStackTrace();
        return;
      }

      System.out.println("Attempting to play Midi");
      sequencer.start();
    }
  }
  
} 

MIDI ファイルを指す引数を 1 つ指定してプログラムを実行すると、プログラムは再生されますが、引数が 2 つあり、シーケンサーを選択するように求められた場合は、何も表示されません。print ステートメントが発生すると、シーケンサーは確実に設定され、プログラムは midi がまだ再生されているかのようにすぐには終了しませんが、ノイズは発生しません。

GUI ベースの MRE

この MRE は、コマンド ライン アプリを GUI に変換して、操作しやすくしました。

このコードをテストするには:

  1. GUI を起動する
  2. テキスト フィールド (上部) が有効な MIDI ファイルを指していることを確認します。
  3. 以下のリストからシーケンサーを 1 つ選択してください
  4. テキストフィールドをクリックしてフォーカスします
  5. フィールドに追加されたアクション リスナーをアクティブにします (Windows では「Enter キーを押す」ことを意味します)。

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;
import java.util.*;
import javax.sound.midi.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;

public class MidiSequencers {

    private JComponent ui = null;
    Vector<Sequencer> sequencers = new Vector<>();
    public static String URLString = "https://bitmidi.com/uploads/18908.mid";
        // Used on my local system, given the hot-link had problems
        //"file:/C:/Users/Andrew/Downloads/Queen%20-%20Bohemian%20Rhapsody.mid";
    URL url;
    JList sequencerList;

    MidiSequencers() {
        try {
            initUI();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public final void initUI() throws Exception {
        if (ui != null) {
            return;
        }

        ui = new JPanel(new BorderLayout(4, 4));
        ui.setBorder(new EmptyBorder(4, 4, 4, 4));
        
        populateSequencers();
        sequencerList = new JList(sequencers);
        ui.add(new JScrollPane(sequencerList));
        
        JTextField textField = new JTextField(URLString, 10);
        ui.add(textField,BorderLayout.PAGE_START);
        
        ActionListener playListener = new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                Sequencer sequencer = (Sequencer)sequencerList.getSelectedValue();
                playSequence(sequencer);
            }
        };
        textField.addActionListener(playListener);
    }

    private void populateSequencers() throws Exception {
        Sequencer sequencer;

        //Gets default sequencer if only one argument given
        sequencer = MidiSystem.getSequencer();
        sequencers.add(sequencer);

        url = new URL(URLString);

        MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
        MidiDevice device;

        // Populates sequencers list with available sequencers
        for (int i = 0; i < infos.length; i++) {
            try {
                device = MidiSystem.getMidiDevice(infos[i]);
                if (device instanceof Sequencer) {
                    System.out.println(sequencers.size() + ": " + device.getDeviceInfo().getName());
                    sequencers.add((Sequencer) device);
                }
            } catch (MidiUnavailableException e) {
                e.printStackTrace();
            }
        }
    }

    private void playSequence(Sequencer sequencer) {
        if (!sequencer.isOpen()) {
            try {
                sequencer.open();
            } catch (MidiUnavailableException e) {
                e.printStackTrace();
            }
        }
        try {
            sequencer.setSequence(MidiSystem.getSequence(url));
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }

        System.out.println("Attempting to play Midi");
        sequencer.start();
    }

    public JComponent getUI() {
        return ui;
    }

    public static void main(String[] args) {
        Runnable r = () -> {
            try {
                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            } catch (Exception useDefault) {
            }
            MidiSequencers o = new MidiSequencers();

            JFrame f = new JFrame(o.getClass().getSimpleName());
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.setLocationByPlatform(true);

            f.setContentPane(o.getUI());
            f.pack();
            f.setMinimumSize(f.getSize());

            f.setVisible(true);
        };
        SwingUtilities.invokeLater(r);
    }
}
4

1 に答える 1