PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Lame aus Java-Programm starten


mofa84
2006-02-06, 17:26:08
Also ich möchte ne kleine GUI für Lame schreiben, aber ich scheiter jetzt schon:

Wenn ich Lame aus der main-Methode starte, klappt es:
try {
Runtime.getRuntime().exec("lame test.wav");
}
catch (Exception e) {
System.err.println(e.toString());
}

Wenn ich das allerdings auf nen Button lege, startet Lame zwar (im Hintergrund, nächstes Problem) und die Datei test.wav.mp3 wird erstellt, aber nichts berechnet und Lame also auch nicht beendet. (wenn ich waitFor() benutze hängt das Programm so lange bis ich Lame kille)

Das zweite schon angesprochene Probleme ist dass Lame in beiden Fällen unsichtbar startet, also nur im Task-Manager sichtbar ist. Was kann man da machen?

Senior Sanchez
2006-02-06, 18:24:16
Also ich möchte ne kleine GUI für Lame schreiben, aber ich scheiter jetzt schon:

Wenn ich Lame aus der main-Methode starte, klappt es:
try {
Runtime.getRuntime().exec("lame test.wav");
}
catch (Exception e) {
System.err.println(e.toString());
}

Wenn ich das allerdings auf nen Button lege, startet Lame zwar (im Hintergrund, nächstes Problem) und die Datei test.wav.mp3 wird erstellt, aber nichts berechnet und Lame also auch nicht beendet. (wenn ich waitFor() benutze hängt das Programm so lange bis ich Lame kille)

Das zweite schon angesprochene Probleme ist dass Lame in beiden Fällen unsichtbar startet, also nur im Task-Manager sichtbar ist. Was kann man da machen?


Soll das ganze auch auf Linux-Systemen laufen oder ist nur Windows wichtig? Weil bei Windows kannste das über cmd abwickeln, also dass de den kommandozeileninterpreter von win nt/2000/xp startest und darin lame ;)

mofa84
2006-02-06, 18:31:10
kannst du mir mal genauer beschreiben wie du das meinst? Bin nicht so der Profi.

Du meinst also im exec steht nur "cmd" und dann versuchen das mit nem OutputStream zu füttern? Weil mit Parametern geht's glaub ich nicht.
Auf jeden Fall ist die Eingabeaufforderung dann auch wieder unsichtbar.

Muss nur unter Windoof funktionieren.

Abnaxos
2006-02-06, 23:06:34
Also ich möchte ne kleine GUI für Lame schreiben, aber ich scheiter jetzt schon:

Wenn ich Lame aus der main-Methode starte, klappt es:
try {
Runtime.getRuntime().exec("lame test.wav");
}
catch (Exception e) {
System.err.println(e.toString());
}

Wenn ich das allerdings auf nen Button lege, startet Lame zwar (im Hintergrund, nächstes Problem)
Hier erstmal sehr wichtig: Starte einen neuen Thread hierzu. Der ActionListener des Buttons wird im EDT (Event Dispatching Thread) ausgeführt, in dem alles, was mit GUI zu tun hat, ausgeführt wird. Wenn du diesen Thread zu machst, machst du die gesamte GUI zu.

Siehe hierzu auch http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html

und die Datei test.wav.mp3 wird erstellt, aber nichts berechnet und Lame also auch nicht beendet. (wenn ich waitFor() benutze hängt das Programm so lange bis ich Lame kille)
Das allerdings finde ich eher komisch. Könnte jedoch auch darauf zurückzuführen sein, was ich oben erwähnt habe, ich wäre jetzt jedoch nicht imstande, dir eine klare Erklärung abzugeben, was hier abgeht. Ich würde vorschlagen, erstmal das mit den Threads sauber hinzubiegen, dann sehen wir weiter.

mofa84
2006-02-07, 00:03:41
hab es jetzt in nen Thread umgewandelt, hat aber nichts gebracht. :(

Alles genau wie vorher, nur dass die GUI nicht mitgekillt wird.

Bzw. ist das so wie du es gemeint hast?

LameStarter starter = new LameStarter(dateipfad.getText());
starter.start();


public class LameStarter extends Thread {

public LameStarter (String dateipfad) {

try {

Runtime rt = Runtime.getRuntime();

Process pr = rt.exec("lame test.wav"); //ZUM TESTEN

}
catch (Exception e) {
System.out.println(e.toString());
}
}
}





Soo, neue Entdeckung: Wenn ich das Programm so starte, startet Lame wieder, macht aber wieder nichts außer die Datei anlegen, bis ich das Fenster schließe, dann läuft es zu Ende. Muss wohl doch am AWT liegen, das scheint zu blockieren.
public class LameGui {

public LameGui() {
Fenster frame = new Fenster();

frame.validate();
frame.setVisible(true);
frame.setResizable(false);
}

public static void main(String[] args) {


try {
Runtime.getRuntime().exec("lame test.wav");
}
catch (Exception e) {
System.err.println(e.toString());
}
new LameGui();
}

}

Abnaxos
2006-02-07, 00:33:11
Naja, das könnte man sicherlich eleganter und in einem zweiten Schritt effizienter machen, aber im Prinzip habe ich genau das gemeint.

Nächste Frage: Liest du stderr und stdout von LAME aus? Möglicherweise produziert LAME aus irgend einem Grund massenhaft Fehler und bleibt bei der Ausgabe hängen, weil der Buffer voll ist und du das Zeugs nicht abholst.

mofa84
2006-02-07, 00:47:00
Nächste Frage: Liest du stderr und stdout von LAME aus? Möglicherweise produziert LAME aus irgend einem Grund massenhaft Fehler und bleibt bei der Ausgabe hängen, weil der Buffer voll ist und du das Zeugs nicht abholst.hab ich schon probiert, kommt aber nix.

Wie gesagt, so lange AWT auf ist, geht nichts. Sobald das zu ist läuft lame einwandfrei.

http://www.rz.fh-ulm.de/~fgaller/Test.rar

Mit BladeEnc ist es auch so. Bin ich einfach nur zu blöde zum Coden oder ist Java wie so oft einfach nur scheiße?

Abe Ghiran
2006-02-07, 10:30:10
hab es jetzt in nen Thread umgewandelt, hat aber nichts gebracht. :(


So erzeugst du ja auch keinen neuen Thread, zumindest nicht in dem Sinne, daß dein Code nebenläufig ausgeführt wird. Der Code, den du im Konstruktor von LameStarter hast, muß in die run Methode des Threads:

public class LameStarter extends Thread {

private String path;

public LameStarter (String dateipfad) {
this.path = dateipfad;
}

public void run(){
try {

Runtime rt = Runtime.getRuntime();

Process pr = rt.exec("lame test.wav"); //ZUM TESTEN

}
catch (Exception e) {
System.out.println(e.toString());
}
}
}


Grüße, Jan

mofa84
2006-02-07, 10:49:36
So erzeugst du ja auch keinen neuen Thread, zumindest nicht in dem Sinne, daß dein Code nebenläufig ausgeführt wird. Der Code, den du im Konstruktor von LameStarter hast, muß in die run Methode des Threads:

public class LameStarter extends Thread {

private String path;

public LameStarter (String dateipfad) {
this.path = dateipfad;
}

public void run(){
try {

Runtime rt = Runtime.getRuntime();

Process pr = rt.exec("lame test.wav"); //ZUM TESTEN

}
catch (Exception e) {
System.out.println(e.toString());
}
}
}


Grüße, Janhat nichts gebracht, auch nicht wenn ich run() synchronized mache :(

Lame encoded weiterhin erst wenn ich das GUI-Fenster schließe.

Abnaxos
2006-02-07, 11:24:46
So erzeugst du ja auch keinen neuen Thread, zumindest nicht in dem Sinne, daß dein Code nebenläufig ausgeführt wird. Der Code, den du im Konstruktor von LameStarter hast, muß in die run Methode des Threads:
Oh, Mist, das habe ich gar nicht gesehen. Naja, war schon spät ... :biggrin: Sorry.

Monger
2006-02-07, 11:30:42
hat nichts gebracht, auch nicht wenn ich run() synchronized mache :(

Lame encoded weiterhin erst wenn ich das GUI-Fenster schließe.

Wie sieht denn deine main() jetzt aus?

Die Threadklasse sieht für mich jetzt so auch richtig aus, ist nur die Frage wie du sie jetzt verwendest.

Btw, geh mit Synchronisierungen GANZ sparsam um! Synchronisier wirklich nur, wenn es gar nicht anders geht.

mofa84
2006-02-07, 11:39:08
^^ da wird nur das GUI-Fenster aufgerufen, sonst nichts.

Kannst dir ja weiter oben runterladen (sieht grad halt etwas chaotisch aus, weil ich alles nur rauskommentiert habe)

Monger
2006-02-07, 12:06:51
^^ da wird nur das GUI-Fenster aufgerufen, sonst nichts.

Kannst dir ja weiter oben runterladen (sieht grad halt etwas chaotisch aus, weil ich alles nur rauskommentiert habe)

Sorry, hab hier leider kein WinRAR auf Arbeit, nur zip. Ich würde nur gern wissen, wo du deinen LameStarter instanziierst und startest.

mofa84
2006-02-07, 12:09:21
So, als Zip: http://www.rz.fh-ulm.de/~fgaller/Test.zip

public void actionPerformed(ActionEvent evt) {
Object src = evt.getSource();
if(src==los) {


LameStarter starter = new LameStarter(dateipfad.getText());
starter.start();

Monger
2006-02-07, 12:21:16
Den ultimativen Grund hab ich jetzt noch nicht gefunden, aber ich empfehle dir zwei Sachen:

1) Kein synchronized! Du machst dir mehr damit kaputt als du rettest. In deinem Fall brauchst du überhaupt nicht zu synchronisieren, und ein synchronized im Methodenkopf ist immer die schlechteste aller Möglichkeiten.

Das synchronized Pattern (falls du es mal brauchst), sieht so aus:


class A{

private Object mutex = new Object();

public void methodA(){

synchronize(mutex){
// hier zu synchronisierende Schritte einfügen
}
}

}



IMMER auf ein eigens dafür gedachtes Objekt synchronisieren!

2) Trenn mal die main von der GUI. Ich hab gesehen dass du das in deinem richtigen Programm schon gemacht hast, aber ich würds auch im Test so machen. Ich selbst hab da schlechte Erfahrungen gemacht...

Also:



class Main{
public void main(){
Gui gui = new Gui();
}
}