Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
ich habe ein großes Problem, ich möchte, dass mein Programm nur einmal aufgerufen wird, und wenn man nochmal auf das jar klick soll es sich nicht nochmal öffnen.
Wie kann ich also feststellen, ob mein Programm bereits ausgeführt wird?
Es wäre auch günstig, wenn ich dem bereits laufenden Programm daten von einem anderen Programm übergeben könnte ....
naja, das ganze ist so: Ich programmiere einen MediaPlayer und wenn man eine wav datei anklickt und der Player bereits ausgeführt wird soll sich kein neuer öffnen sondern diese wav datei im bereits ausgeführten player wiedergegeben werden .....
Problem ist, dass für jede Anwendung ne eigene VM gestartet wird, somit kommst du mit nem Singleton-Pattern nicht wei.
Die einzige Möglichkeit die ich wüsste wäre folgende:
Wenn dein Proggy zum ersten mal aufgerufen wird schreibst du ne Datei irgendwo hin. Am besten Temp oder sowas. Dann überprüfst du in der main eben immer, ob das Programm schon existiert.
Code:
main(){
File f = new File("c:/Temp/meinProgy.abc");
if(f.exists()){
//abbrechen, proggy läuft schon
} else{
f.createNewFile();
f.deleteOnExit();
//Proggy starten
}
}
Natürlich solltest du den Pfad wo die Datei gespeichert wird nicht hardcoden sondern über ne Systemproperty einlesen.
Bei Programmstart erstellst du dir nen ordner im Temp-Ordner.
Dann hängst du da nen DirectoryListener rein, der den Ordner scannt. Wenn ne neue Datei hinzukommt bearbeite sie.
In die Datei kannst du z.B. den Pfad der zu spielenden Datei schreiben. Dann löschst du die Datei wieder.
Beispiel
deine main methode
Code:
main(){
File f = new File("c:/Temp/meinProgy.abc");
if(f.exists()){
File play = new File("c:/Temp/blahblub/datei.abc);
FileWriter writer = new FileWriter(play);
writer.writeln(<pfad zur wav datei>);
writer.flush();
writer.close();
//jetzt proggy beenden
} else{
f.createNewFile();
f.deleteOnExit();
//Proggy starten
}
}
DirectoryMonitor
Code:
import java.io.File;
import java.io.FileFilter;
import java.util.HashMap;
import java.util.Vector;
public class DirectoryMonitor implements Runnable {
private long interval;
private File directory;
private Thread monitor;
private Vector listeners;
private boolean stopped;
private boolean daemon;
private static final FileFilter filter = new FileFilter() {
public boolean accept(File arg0) {
return true;
}
};
public DirectoryMonitor(String directory, long interval) {
this.interval = interval;
this.directory = new File(directory);
if (!this.directory.exists() && !this.directory.canRead()
|| !this.directory.isDirectory())
throw new IllegalArgumentException("Fehler");
listeners = new Vector();
}
public void addDirectoryChangeListener(DirectoryChangedListener dcl) {
listeners.add(dcl);
}
public void removeDirectoryChangeListener(DirectoryChangedListener dcl) {
listeners.remove(dcl);
}
public void startMonitoring() {
stopMonitoring();
stopped = false;
monitor = new Thread(this);
monitor.setDaemon(daemon);
monitor.start();
}
public void stopMonitoring() {
stopped = true;
try {
if (monitor != null) {
monitor.interrupt();
monitor.join();
}
} catch (InterruptedException e) {
}
monitor = null;
}
public void setDaemon(boolean daemon) {
daemon = daemon;
if (monitor != null) {
monitor.setDaemon(daemon);
}
}
public void run() {
File[] prevList = directory.listFiles(filter);
checkAdditions(prevList, new HashMap());
HashMap prevMap = toMap(prevList);
while (true) {
try {
Thread.sleep(interval);
} catch (InterruptedException e) {
// ignore
}
if (stopped == true) {
return;
}
File[] currList = directory.listFiles(filter);
HashMap currMap = toMap(currList);
checkAdditions(currList, prevMap);
checkRemovals(prevList, currMap);
prevList = currList;
prevMap = currMap;
}
}
private HashMap toMap(File[] files) {
int len = files.length;
HashMap map = new HashMap();
for (int i = 0; i < len; ++i) {
map.put(files[i].toString(), files[i]);
}
return map;
}
private void checkAdditions(File[] curr, HashMap prev) {
int len = curr.length;
int type = DirectoryChangedEvent.FILE_ADD;
for (int i = 0; i < len; ++i) {
if (prev.get(curr[i].toString()) == null) {
DirectoryChangedEvent dce = new DirectoryChangedEvent(curr[i],
type);
fireNotify(dce);
}
}
}
private void checkRemovals(File[] prev, HashMap curr) {
int len = prev.length;
int type = DirectoryChangedEvent.FILE_REM;
for (int i = 0; i < len; ++i) {
if (curr.get(prev[i].toString()) == null) {
DirectoryChangedEvent dce = new DirectoryChangedEvent(prev[i],
type);
fireNotify(dce);
}
}
}
private void fireNotify(DirectoryChangedEvent dce) {
Vector list = (Vector) listeners.clone();
int len = list.size();
for (int i = 0; i < len; ++i) {
DirectoryChangedListener dcl = (DirectoryChangedListener) list
.get(i);
dcl.directoryChanged(dce);
}
}
}
DirectoryChangedListener
Code:
public interface DirectoryChangedListener {
public void directoryChanged(DirectoryChangedEvent evt);
}
DirectoryChangedEvent
Code:
import java.util.EventObject;
public class DirectoryChangedEvent extends EventObject{
public static int FILE_ADD = 0;
private int typ;
public DirectoryChangedEvent(Object source, int typ){
super(source);
this.typ = typ;
}
public int getTyp(){
return typ;
}
}
Initialisierung des Listeners:
Code:
DirectoryMonitor dm = new DirectoryMonitor("c:/Temp/blahblub/", 500);
dm.addDirectoryChangeListener(new DirectoryChangedListener() {
public void directoryChanged(DirectoryChangedEvent dce) {
File file = (File) dce.getSource();
if (dce.getTyp() == DirectoryChangedEvent.FILE_ADD) {
//datei einlesen und wieder löschen
}
}
});
dm.setDaemon(true);
dm.startMonitoring();
Den FileFilter musst du anpassen (DirectoryMonitor). Den ScanPfad musst du anpassen (Initialisierung des Listeners).
Deine Main musst du auch anpassen
naja, das sind schon mal gute antworten an die ich gar nicht gedacht habe, aber wie sieht es mit der Performance aus, wenn ich von mir aus jede Sekunde den Ordner nach neuen Aufgaben scanne? Mein Player braucht ohne hin schon 30 % auslastung von meinem AMD Athlon (1,1Ghz); allerdings nur im Vollbetrieb. Bei einem solchen "scan" verfahren würde es zwar gehen aber ich glaube, dass die performance darunter leidet. Ich werde es einfach mal versuchen und bin sehr dankbar für diese Lösung. Ich dachte nämlich, dass das mit der Klasse "System" gehen könnte, fand aber nichts passendes.
Ich würde den Vorschlag mit dem Temp Directory sofort umsetzen, nur ist der Player ohnehin schon "etwas" langsamer, da ich Swing verwende, um ihn auch unter linux betreiben zu können. Ich habe ihn ja deswegen mit meinen Kollegen entwickelt, unter der Vorrausetzung, einen schnellen Player zu erstellen der viele Funktionen bietet und auch Linux fähig ist; weiters auch Benutzerfreundlich aufgebaut ist. Eigentlich hätte ich bereits alles nötige mal Programmiert, mir fehlt nur noch der .cda Support und eventuell eine Brenn-funktion zum brennen von CDs was glaube ich aber nicht möglich ist.
Er kann jetzt von Microphon und Digital-Kamera sachen aufnehmen, in andere Formate exportieren, Playlists, MP3 ID3 Daten lesen/ändern/erstellen, Spiele, Such-Tools, DVD spielen unter Windows (voraussetzung PowerDVD installiert, möchte aber JFFMPEG dafür verwenden, um auf den Codec von PowerDVD zu verzichten), Bilder anzeigen/bearbeiten/exportieren, mit Java3D Plugins 3d datein anzeigen, Visualisierungen, kleine Analyse Tools, abspielen aller Formate die JMF unterstüzt.
Mich würde weil es gerade hier dazu passt gerne interessieren: Was erwartet ihr euch von einem Player der Freeware/Open-Source ist; was sollte er können, was abspielen, wie aussehen ......
- Geschwindigkeit spielt nicht sooo eine große Rolle, solange ich nicht ewige Wartezeiten hab.
- Er sollte sämtliche Formate abspielen können, nach Möglichkeit OHNE 100 Codecs zu installieren
- Visualisierung ist mir sch**s egal
- Er sollte Videos abspielen können (auch alle Formate)
- Man sollte Einstellungsmöglichkeiten bei Videos haben (Bild an Bildschirm anpassen, Prozentual vergrößern, Helligkeit anpassen u.s.w.)
- Er sollte AUF JEDEN FALL auch über nen TV-Out an den Fernseher gepackt werden können (Zoomplayer kann das z.B. nicht)
- Benutzerfreundlich, d.h.: EIN Fenster und Optionen erscheinen in nem Dialog, keine überfüllten Rechtsklick-Menüs...
hm..was noch..kA
Ach ja, der DirectoryScanner ist meiner Meinung nicht sonderlich langsam. Ich denke auch net, dass der den Recher arg belastet.
Du musst nur ne möglichkeit finden, wie du die Infos über den abzuspielenden Song gescheit in der Datei speicherst.
Andere Möglichkeit die mir gerade einfällt (dürfte ziemlich schnell sein):
Lass intern in deinem Programm nen Server laufen. Wenn das Programm ein zweites mal gestartet wirt (anhand einer DAtei überprüfen) baust du ne Socket-Verbindung zum Server auf und schickst den Pfad zum abzuspielenden Song)
Pseudocode
Programm starten
Programm zum ersten mal gestartet?
:ja
programm ganz normal laden
serversocket öffnen und an localhost, port xyz lauschen lassen
fortfahren mit dem programm
:nein //programm "doppelt"
Clientverbindung (socket) zu localhost, port xyz aufbauen
pfad zu der zu spielenden datei senden
verbindung schließen
programm beenden
: hauptprogramm
server akzeptiert verbindung
server öffnet den inputstream
server liest eine zeile
server schließt verbindung auf wartet erneut auf connect
datei abspielen
Codebeispiele
Code:
public static void main(String[] args){
File f = new File("c:/Temp/meinProgy.abc");
if(f.exists()){
//abbrechen, proggy läuft schon
startClient(args[0]);
} else{
f.createNewFile();
f.deleteOnExit();
//Proggy starten
startServer();
}
}
public void startServer(){
ServerSocket sock = new ServerSocket(80);
while(true){
Socket socket = sock.accept();
BufferedReader reader = new BufferedReader(InputStreamReader(sock.getInputStream()));
String line = reader.readLine();
reader.close();
socket.close();
playSong(line);
}
}
public void startClient(String pathToSong){
Socket socket = new Socket("localhost", 80);
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
writer.writeln(pathToSong);
writer.write("\r\n"); // weiß net genau ob du das explizit mit senden musst
writer.flush();
writer.close();
socket.close();
System.exit(1);
}
Vielleicht gibts ne schnellere Möglichkeit als ne SocketVerbindung, keine Ahnung...
Edit:
Ich weiß net genau, was passiert wenn dein programm durch nen Doppelklick auf ne .wav Datei gestartet wird. Wird als Argument der Pfad zur exe übermittelt ? Oder wird ein File übergeben ?
Ich bin davon ausgegangen, dass als Argument(0) der Pfad übermittelt wird
Der Pfad zur Datei wird auch als args in der main Methode übermittelt sodass eine Datei eingentlich gar nicht nötig ist.
Zur deiner Meinung mit den vielen Kontextmenü Lösungen kann ich entwarnung geben, ich hasse auch nichts mehr wenn man alles über Kontextmenü steuern muss. Also habe ich einfach beides gemacht. Ich habe wie man es vom Windows Media Player kennt die Tapps oben eingefügt, die direkt ein Optionen Fenstern im Player aufrufen, bei Klick auf Wiedergabe kommt halt wieder die Playlist und die Visualisierung. Außerdem lässt sich das ganze mit Shortcuts (Tastatur) steuern.
Zu der Frage mit den Formaten: Sicherlich kenne ich mittlerweile Mittel und Wege, wie ich mit JMF so ziemlich alles native, allso ohne Windows Codecs abspielen kann. Sogar DVD, SVideo, DivX etc. Leider bin ich mir nicht ganz über den Rechten im klaren. Ich gehe eher auf Nummer sicher alls in Rechtsstreit zu geraten. Wenn sich da wer besser über Media-Patente auskennt, dann bitte posten. Den wenn ich z.B. FFMPEG ohne weiteres einbinden darf wäre die Palette der Formate auch für Linux User größer. Unter Windows nutzt JMF ja die Windows Codecs was finde ich nicht gut ist, den für was hat man den einen Player, wenn man erst wieder den Windows Media Player installieren muss, damit was geht. Klar biete JMF wav, mp3, au, avi, mov und gsm support, aber das ist meiner Meinung nach nicht genug.
Vor kurzem habe ich das mit dem Server probiert und es geht, ich kann auf mein Programm zugreifen. Außerdem kann ich durch einen "Hello" aufruf, allso schicke diese Nachricht an den Server und kommt was zurück, dann weiß ich, aha, der player läuft bereits.
Bin weiter auf eure Meinung gespannt und bedanke mich vorerst mal für die Idee mit dem Server.