MidiDevice-Object übergeben : geht nicht!?

screaper

Mitglied
Hallo Java Gemeinde.

Ich möchte ein MidiDevice-Objekt einer anderen Klasse übergeben.

Momentan habe ich eine Klasse MidiSettings. Dort kann man das gewünschte Midigerät auswählen. Diese speichere ich dann in einer private Variablen ab und stelle dazu die Methode: public MidiDevice returnMidiDevice(){} zur Abfrage bereit.

In der anderen Klasse generiere ich dann eine Instanz die sich den benötigten Treiber dann mit returnMidiDevice holt.

Frage ich nun in der neuen Klasse das Midigerät ab, dann erhalte ich den richtigen Wert. Also den, den returnMidiDevice geliefert hat.

Jetzt wird in dieser Klasse wieder eine Instanz einer andere Klasse erzeugt, die im Konstruktor das eben zur Verfügung gestellte MidiDeviceObjekt benutzt.
Wenn ich in der eben generierten Instanz der neuen Klasse nun das verwendete MidiDevice abfrage erhalte ich wieder das korrekte.

Soweit so gut!

Wenn ich das Gerät nun verwende bekomme ich eine MidiUnavailabeException!

Das ist mir unerklärlich, denn wenn ich das Gerät in der als letztes erzeugten Instanz manuell eingebe erhalte ich keine Fehlermeldung und es funktioniert.

Kann es sein, dass das MidiDevice von dem ersten Aufruf meiner MidiDevice-Klasse blockiert wird und ich es deshlab nicht verwenden kann? Es wird aber nirgends geöffnet. Nur in der letzten Klasse. Ich hole mir lediglich das Device und reiche es weiter.


Ich hoffe es ist nciht zu kompliziert erklärt.

Hat jemand eine Ahnung?

Gruß Marco
 
Hallo,
ich bekomme eine MidiUnavailableException.

Quellcode anbei.

Klasse die das Gerät verwenden soll
PHP:
public MidiOutMetronom (MidiDevice mDevice){
	
		
		
		try 	{
				
					//Hier wird das MidiGerät übergeben, was vorher ausgewählt werden sollte.
					midiDevice = mDevice;
					
	/*		midiDevice =  MidiSystem.getMidiDevice(MidiSystem.getMidiDeviceInfo()[3]);
				*/	System.out.println(midiDevice.getDeviceInfo().getName());
			
				
		// öffne das Gerät, falls noch nicht offen:
		if (!midiDevice.isOpen())midiDevice.open();
			
		 receiver = midiDevice.getReceiver(); 
		 midiClock.setMessage(ShortMessage.TIMING_CLOCK);
		 
		 	 
		}
		
		catch (MidiUnavailableException e){
			System.out.println("Es ist kein Midigerät verfügbar!");
		}
		catch (Exception e){
			System.out.println("Es gab nicht näher spezifizierte Probleme!");
		}
		
	}



Hier die Klasse die das Gerät auswählt:

PHP:
package gui;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;
import javax.sound.midi.*;


public class MidiOutDialog extends JDialog{


	private JComboBox midiDevices = new JComboBox();
	private MidiDevice actualMidiDevice;
	private JLabel label = new JLabel("Bitte das gewünschte Gerät auswählen");
	private JButton ok_button = new JButton("OK");
	private GridBagLayout gbl = new GridBagLayout();
	private GridBagConstraints gbc;
	
	
	public MidiOutDialog(){
			
		super.setTitle("Midigerät wählen");
		
		initMidiDevice();
					
			midiDevices.addActionListener(new ActionListener(){
				public void actionPerformed(ActionEvent e){
						performSelection(midiDevices.getSelectedItem());
					
				}
			});
			
			ok_button.addActionListener(new ActionListener(){
				public void actionPerformed(ActionEvent e){
					//
				}
			});
			
			
			
			this.setLayout(gbl);
			
			gbc = new GridBagConstraints();
			gbc.gridx=0;
			gbc.gridy=0;
			gbc.gridwidth=1;
			gbl.addLayoutComponent(label, gbc);
			this.add(label);
			
			gbc = new GridBagConstraints();
			gbc.gridx=0;
			gbc.gridy=1;
			gbc.gridwidth=1;
			gbl.addLayoutComponent(midiDevices, gbc);
			this.add(midiDevices);
			
			gbc = new GridBagConstraints();
			gbc.gridx=0;
			gbc.gridy=2;
			gbc.gridwidth=2;
			gbl.addLayoutComponent(ok_button, gbc);
				
			//this.add(ok_button);
			
			this.setModal(true);
			this.setBounds(100, 100, 330, 300);
		}
	

		private void initMidiDevice(){
			int anzahl = MidiSystem.getMidiDeviceInfo().length;
			for (int i = 0; i<anzahl; i++){
				midiDevices.addItem(MidiSystem.getMidiDeviceInfo()[i].getName());
				
				}
			}
		
		private void performSelection(Object selected) {
				
			try {
				actualMidiDevice = MidiSystem.getMidiDevice(MidiSystem.getMidiDeviceInfo()[midiDevices.getSelectedIndex()]);
				System.out.println(actualMidiDevice.getDeviceInfo().getName());
			} catch (MidiUnavailableException e) {
				throwMidiUnavailable();
				e.printStackTrace();
			}
		}

		public MidiDevice returnMidiDeviceNumber(){
			return actualMidiDevice;
		}
		
		
		
		
		
	private void throwMidiUnavailable(){
		 JOptionPane.showMessageDialog(this,"Keine Midischnittstelle vorhanden!"	 
			 		,"Midifehler!", JOptionPane.ERROR_MESSAGE);
	}
		
	
	
}



Wie gesagt, ausgegeben (das richtige Gerät) wird es auch in der MidiOutMetronom Klasse. Nur verwendenden kann ich es dort nicht. Da kommt die Exception.
Den ganzen Quellcode kann ich hier nciht veröffentlichen, da er zu lang ist.
 
Wo übergibst Du der MidiOutMetronom-Klasse das MidiDevice-Objekt?

Was passiert, wenn du folgende Zeile wieder aktivierst (die Kommentare entfernst):

Code:
midiDevice =  MidiSystem.getMidiDevice(MidiSystem.getMidiDeviceInfo()[3]);
 
So hole ich mir manuell das Midigerät. Und das funktioniert auch. Aber das programm soll ja nicht nur auf meinem PC laufen, sondern auf diversen und so muss der user dann den Midiout-Port seiner Soundkarte auswählen. Dafür ist der Dialog da.

Wenn ich das Mididevice abfrage bekomme ich ja die werte vom dialog. Also es passt. Nur wenn ich es verwenden will gehts nicht. die manuelle variante geht 100%ig.
 
Der Code wo Du die MidiOutMetronom-Klasse mit dem MidiDevice-Objekt instanzierst wäre trotzdem noch hilfreich.

Hast Du schoneinmal probiert nur das MidiDevice.Info-Objekt durchzuschleusen und Dir damit das MidiDevice-Objekt zu holen?

Also Anstelle von:

Java:
midiDevice =  MidiSystem.getMidiDevice(MidiSystem.getMidiDeviceInfo()[3]);

zB

Java:
public MidiOutMetronom (MidiDevice.Info midiDeviceInfo) {
    try {
        midiDevice =  MidiSystem.getMidiDevice(midiDeviceInfo);
    } catch {
    // ...
 
Zuletzt bearbeitet von einem Moderator:
im Prinzip, kann die klasse als standalone komponente verwendet werden, indem du einfach eine main-methode machst und die klasse instantiierst.

Ich muss aber das MidiObjekt übergeben. Das info is quatsch, weil ich ja nicht die geräteübersicht übergeben will sondern nur ein objekt.

Alternativ kannst du mir auch eien vorschlag zur implemnierung machen.

Ich brauch einen Dialog der mir die Midigeräte zur auswahl stellt und ich dann das gewünschte auswählen kann.
Dann wird dieses Gerät für das MidiOutMetronom verwendet.

Ansich ganz einfach.... Ich frage mich nur, ob das Gerät dann von der Dialogklasse geblockt wird, (obwohl ich es nicht öffne). Aber eine CannotOpenMidiDeviceException wird ja auch nciht ausgelöst, sondern es sagt die ist nciht vorhanden.

Ich könnte höchstens versuchen die Einträge der ComboBox mit Intergerwerten zu hinterlegen. UNd diese Werte dann an die Metronomklasse übergeben. Dort generiere ich dann nochmal das DeviceINfoArray und wähle dann das Device mit der übergebenen nummer aus. (Quasi so wie ich jetzt manuell das Gerät auswähle)

Hierzu habe ich aber dann eine Frage: Kann es sein, dass sich die Reiehnfolge der Geräte beim auslesen der Info ändert? Das wäre dann schlecht, denn dann passt das ausgewählte Device nicht mehr zur Selektion in der MetronomKlasse. Deshalb hab ich das so noch nciht probiert. Außerdem finde ich es "unschön".


Sorry für die vielen tippfehler. ich schreib gard mitm handy...
 
Also ich hab jetzt nur in einem kleinen Beispiel soetwas ähnliches selbst probiert und bisher keine Exception bekommen:

Java:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.sound.midi.MidiSystem;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.MidiDevice.Info;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JOptionPane;

public class MidiTest extends JFrame implements ActionListener {

    private JComboBox midiDeviceList = null; 
    
    public MidiTest() {
        super("Midi Test");
        initComponents();
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        pack();
        setLocationRelativeTo(null);
        setVisible(true);
    }
    
    private void initComponents() {
        midiDeviceList = new JComboBox();
        Info[] midiDevices = MidiSystem.getMidiDeviceInfo();
        for(int i = 0; i < midiDevices.length; i++) {
            midiDeviceList.addItem(midiDevices[i]);
        }
        midiDeviceList.addActionListener(this);
        add(midiDeviceList);
    }
    
    public void actionPerformed(ActionEvent e) {
        if(e.getSource() == midiDeviceList) {
            try {
                MidiOutMetronom metronom = new MidiOutMetronom((Info) midiDeviceList.getSelectedItem());                
            } catch(MidiUnavailableException exc) {
                exc.printStackTrace();
                JOptionPane.showMessageDialog(this, "Midi device unavailable", "Error", JOptionPane.ERROR_MESSAGE);
            }
        }
    }
    
    public static void main(String[] args) {
        new MidiTest();
    }
}

Java:
import javax.sound.midi.MidiDevice;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.MidiDevice.Info;

public class MidiOutMetronom {
    
    private MidiDevice midiDevice = null;
    
    public MidiOutMetronom(Info midiDeviceInfo) throws MidiUnavailableException {
        try {
            midiDevice = MidiSystem.getMidiDevice(midiDeviceInfo);
            if (!midiDevice.isOpen()) {
                midiDevice.open();
                System.out.println("Device " + midiDevice.getDeviceInfo() + " opened.");
            }
        } finally {            
            midiDevice.close();
            System.out.println("Device closed.");
        }
    }
}
 
Zuletzt bearbeitet von einem Moderator:
Hi,
und das Funktioniert? Welches Gerät wird denn verwendet? Da wird doch nur die Info übergeben, oder? Hast du mal was auf dem Gerät ausgegeben?
Da nix angegeben ist, wählt Java automatisch den default Synthesizer.

Ich werde deine Version mal probieren!
Danke Dir!

Aber hast du eien Idee, warum meine Version nicht funktioniert?
 
Guten Morgen!

Genau weiß ich nicht wo bei deinem Code das Problem liegt, vielleicht machst du ein kleines lauffähiges Beispiel, wo das Problem auftritt.

Ich hab mal meine MidiOutMetronom-Klasse um einen Konstruktor erweitert:

Java:
public class MidiOutMetronom {

    private MidiDevice midiDevice = null;

    public MidiOutMetronom(Info midiDeviceInfo) throws MidiUnavailableException {
        this(MidiSystem.getMidiDevice(midiDeviceInfo));
    }

    public MidiOutMetronom(MidiDevice midiDevice) throws MidiUnavailableException {
        this.midiDevice = midiDevice;
        try {
            if (!midiDevice.isOpen()) {
                this.midiDevice.open();
                System.out.println("Device " + midiDevice.getDeviceInfo() + " opened.");
            }
        } finally {
            midiDevice.close();
            System.out.println("Device closed.");
        }
    }
}

Und mit deinem JDialog verwendet:

Java:
                actualMidiDevice = MidiSystem.getMidiDevice(MidiSystem.getMidiDeviceInfo()[midiDevices.getSelectedIndex()]);
                System.out.println(actualMidiDevice.getDeviceInfo().getName());
                new MidiOutMetronom(actualMidiDevice);

Funktioniert alles einwandfrei - keine Exception. Direkt etwas ausgeben am MidiDevice tue ich nicht, aber ich kann alle auswählen und ohne Probleme öffnen (und schließen). Ein Beispiel meiner Ausgabe:

Code:
Device Microsoft GS Wavetable SW Synth opened.
Device closed.
Device Real Time Sequencer opened.
Device closed.
Device Java Sound Synthesizer opened.
Device closed.
Device Microsoft MIDI-Mapper opened.
Device closed.
 
Zuletzt bearbeitet von einem Moderator:
Zurück