pure.mp3 Entwicklungsthread - Hilfe ist gerne gesehen!

Gruß Thomas!

Grand Admiral Special
Mitglied seit
27.03.2008
Beiträge
2.027
Renomée
118
Standort
Bayreuth
  • Docking@Home
Hallo,

Ich bin derzeit am rumbasteln mit Clips unter Java. Ich will Musik abspielen damit. Auf jeden Fall ging das gestern noch, aber plötzlich nicht mehr. Daher wollte ich fragen, ob nicht doch ein Fehler im Code ist.

PHP:
package pure_mp3;
/*
 *	ClipPlayer.java
 *
 *	This file is part of jsresources.org
 */

/*
 * Copyright (c) 1999 - 2001 by Matthias Pfisterer
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
|<---            this code is formatted to fit into 80 columns             --->|
*/

import java.io.IOException;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineListener;
import javax.sound.sampled.LineUnavailableException;

public class ClipTest implements LineListener //umschreiben, dass es Clip erzeugt, und dann zurückgibt.
// Es fehlt also noch eine getClip() Methode.
{
	private Clip		m_clip;

	public ClipTest()
	{
		AudioInputStream	audioInputStream = null;
		try
		{
			audioInputStream = AudioSystem.getAudioInputStream(new java.net.URL("file:music.mp3"));
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
		if (audioInputStream != null)
		{
			AudioFormat	format = audioInputStream.getFormat();
			if ( format.getEncoding() != AudioFormat.Encoding.PCM_SIGNED ) {
			      // if ((audioFormat.getEncoding() != AudioFormat.Encoding.PCM) ||
			      //     (audioFormat.getEncoding() == AudioFormat.Encoding.ALAW) || 
			      //     (audioFormat.getEncoding() == AudioFormat.Encoding.MP3)) {
			         AudioFormat newFormat = new AudioFormat(
			            AudioFormat.Encoding.PCM_SIGNED, 
			            format.getSampleRate(),
			            16,
			            format.getChannels(),
			            format.getChannels() * 2,
			            format.getSampleRate(),
			            false );
			         System.out.println( "Converting audio format to " + newFormat );
			         AudioInputStream newStream = AudioSystem.getAudioInputStream( newFormat, audioInputStream );
			         format = newFormat;
			         audioInputStream = newStream;
			      }
			DataLine.Info	info = new DataLine.Info(Clip.class, format);
			try
			{
				m_clip = (Clip) AudioSystem.getLine(info);
				m_clip.addLineListener(this);
				m_clip.open(audioInputStream);
			}
			catch (LineUnavailableException e)
			{
				e.printStackTrace();
			}
			catch (IOException e)
			{
				e.printStackTrace();
			}
			m_clip.loop(0);
		}
	}

	public void update(LineEvent event)
	{
		if (event.getType().equals(LineEvent.Type.STOP))
		{
			m_clip.close();
		}
		else if (event.getType().equals(LineEvent.Type.CLOSE))
		{
			System.exit(0);
		}

	}
	
	public static void main(String args[])
	{
	  ClipTest clipTest = new ClipTest();
	}
}
.
EDIT :
.

Okay. Kommando zurück. Ich hatte da was rausgelöscht, was aber so unbedingt drinsein musste.

PHP:
public static void main(String[] args)
	{
			File	clipFile = new File("music.mp3");
			int		nLoopCount = 0;
			ClipPlayer	clipPlayer = new ClipPlayer(clipFile, nLoopCount);

			/* In the JDK 5.0, the program would exit if we leave the
			   main loop here. This is because all Java Sound threads
			   have been changed to be daemon threads, not preventing
			   the VM from exiting (this was not the case in 1.4.2 and
			   earlier). So we have to stay in a loop to prevent
			   exiting here.
			*/
			while (true)
			{
				/* sleep for 1 second. */
				try
				{
					Thread.sleep(1000);
				}
				catch (InterruptedException e)
				{
					// Ignore the exception.
				}
			}
	}
.
EDIT :
.

Wird aber bei meinem Zweck wohl rausfliegen müssen. Ich hab das Problem ja nicht, weil das ganze aus ner GUI gestartet werden soll.
 
Die Lösung mit dem Sleep ist aber auch ganz, ganz eklig. So was ist richtig schlechter Stil und das sollte man sich gar nicht erst angewöhnen.

Du solltest lieber sehen, dass du die Thread ID des Audio Streams bekommst und dann in der main() oder im der playermethode selbst auf das beenden des Threads warten.
 
Ich hab es jetzt eh anders gemacht. Der Clip hat mir zum buffern zu lange gebraucht. Jetzt hab ich einen eigenen Player geschrieben der sogar threadsafe ist. :) Wenn der Player fertig ist, gibts den Sourcecode hier :)
 
Wenn du Open Souce entwickelst wäre auch github was für dich. Da können dann andere Leute "sozial" Coden. :P

Grüße,
anopheles
 
Mal ne Frage. Ich bin gerade am grübeln, ob man mit einem AudioInputStream die Position in einem Lied feststellen könnte. Aber das scheint nicht zu gehen oder?

PHP:
package pure_mp3;

import java.net.URL;
import java.io.IOException;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.FloatControl;



public class MusicStreamer extends Thread{
	
	private static final int	EXTERNAL_BUFFER_SIZE = 128000;
	private AudioInputStream audioInputStream;
	private SourceDataLine line;
	private AudioFormat audioFormat;
	private DataLine.Info info;
	private static final double linearScalar = Math.log (10.0)/20;
	private static double volume=100.0;
	private boolean suspended = false;
	private volatile boolean stop = false;
	
	public MusicStreamer(String path)
	{
		super();	
		insert(path);
	}
	
	public void insert(String path)
	{
		try
		{
			audioInputStream = AudioSystem.getAudioInputStream(new URL(path));
		}
		catch (Exception e)
		{
			e.printStackTrace();
			System.exit(1);
		}
		
		if (audioInputStream != null)
		{
			AudioFormat	format = audioInputStream.getFormat();
			if ( format.getEncoding() != AudioFormat.Encoding.PCM_SIGNED ) 
			{
		      // if ((audioFormat.getEncoding() != AudioFormat.Encoding.PCM) ||
		      //     (audioFormat.getEncoding() == AudioFormat.Encoding.ALAW) || 
		      //     (audioFormat.getEncoding() == AudioFormat.Encoding.MP3)) {
		         AudioFormat newFormat = new AudioFormat(
		            AudioFormat.Encoding.PCM_SIGNED, 
		            format.getSampleRate(),
		            16,
		            format.getChannels(),
		            format.getChannels() * 2,
		            format.getSampleRate(),
		            false );
		         AudioInputStream newStream = AudioSystem.getAudioInputStream( newFormat, audioInputStream );
		         format = newFormat;
		         audioInputStream = newStream;
		   }
		}
		audioFormat = audioInputStream.getFormat();
		info = new DataLine.Info(SourceDataLine.class,audioFormat);
	}

	public void run()
	{
		try
		{
			line = (SourceDataLine) AudioSystem.getLine(info);
			line.open(audioFormat);
			line.start();			
			setVolume(volume);
		}
		catch (Exception e)
		{
			System.out.println("FAIL");
			e.printStackTrace();
			System.exit(1);
		}
		int	nBytesRead = 0;
		byte[]	abData = new byte[EXTERNAL_BUFFER_SIZE];
		while (nBytesRead != -1 && !stop)
		{
			synchronized(this) 
			{
                while (suspended && !stop )
                	try
                	{
                		wait();
                	}
                	catch(Exception e)
                	{
                	}
            }
			try
			{		
				System.out.println(line.getMicrosecondPosition());
				nBytesRead = audioInputStream.read(abData, 0, abData.length);
			}
			catch (IOException e)
			{
				e.printStackTrace();
			}
			if (nBytesRead >= 0)
			{
				line.write(abData, 0, nBytesRead);
			}
		}
		line.drain();
		line.close();
		
	}
	
	public synchronized void pause()
	{
		suspended = !suspended;
		notify();
	}
	
	public synchronized void stop_()
	{
		stop = true;
		notify();
	}
	
	public void setVolume(double xVolume)
	{
		volume = xVolume;
		if( line.isControlSupported( FloatControl.Type.MASTER_GAIN ) ) {
			xVolume = xVolume/100.0d; 
            FloatControl volume = (FloatControl) line.getControl( FloatControl.Type.MASTER_GAIN );
            double minGainDB = volume.getMinimum ();
            double ampGainDB = ( (10.0f/20.0f)*volume.getMaximum ())-volume.getMinimum (); 
            double valueDB = minGainDB+ (1/linearScalar)*Math.log (1+ (Math.exp (linearScalar*ampGainDB)-1)*xVolume);
            volume.setValue((float) valueDB); 
         }
	}
	
	public static void setVolume2(double xVolume)
	{
		volume = xVolume;
	}

Ich weiß nicht, ob ich das nicht einfach umgehen soll, indem ich das hier benutze:

http://www.javazoom.net/jlgui/developerguide.html
.
EDIT :
.

Okay, das Problem kann man ja eigentlich damit beheben, indem man die Bytes, die eingelesen werden in einer Variable mitzählt, oder nicht?

Das Problem besteht im Grunde jetzt darin, dass ich nicht weiß, wie ich an die Länge des Streams komme...
.
EDIT :
.

Da ich mir gerade mal ein paar Beispiele zu sowas im Netz angesehen habe, kriege ich das Gefühl, dass das ganze hier gar nicht notwendig ist. Man kann ja über die Tags in einer .mp3 Datei aulesen, wie lang das Ding ist... Zwar nicht als long aber für einen JSlider zum einstellen müsste das eigentlich reichen?
 
Zuletzt bearbeitet:
Mir ist gerade eine Idee gekommen. Ich könnte ja die Audio Dateien weiterhin als Stream abspielen lassen. Das ist ja soweit kein Problem. Pausieren geht ja auch und so. Wenn ich dann aber in dem Spaß dann springen will könnte ich ja immer einen Clip erzeugen, mir dessen Länge geben lassen und dann von der gewünschten Stelle die Position im Stream geben lassen und dann im eigentlichen Playback Thread dahin springen. Das würde dann zwar ein bischen dauern, dass bis zum entsprechenden Punkt gesprungen werden würde, aber wenn man das in einem Thread realisiert würde das ja den Playback nicht unterbrechen, aber dennoch zum gewünschten Ziel bringen.Wäre auf jeden Fall besser als ein Lag am Anfang des Liedes. Was meint ihr?
.
EDIT :
.

Funktioniert besser als erwartet. Nur die ersten 2 Sekunden passiert erstmal nichts. Aber das ist ja zu verkraften!
.
EDIT :
.

So, jetzt hab ich das nächste Problem.

Ich setze die aktuelle Position im Lied auf einen JSlider. Ich wollte mitdemselben JSlider auch suchen im Lied ermöglichen. Da setValue(int x) aber ein ChangeEvent feuert wird das nichts über den Code hier:

PHP:
        addChangeListener(new ChangeListener()
        {
            public void stateChanged(ChangeEvent e)
            {
                JSlider source = (JSlider)e.getSource();
                if(!source.getValueIsAdjusting())
                {
                    seek((int)source.getValue());
                }
            }
        });

Wie kann ich das umgehen, dass er beim updaten des JSliders ein Event rauswirft? Muss ich mir eine eigene JSlider Klasse schreiben?
 
Da ich das mit dem Slider nicht gebacken krieg, dass der auch für seek gut ist, wollte ich euch mal fragen, wie ich das machen könnte.

PHP:
package pure_mp3;

import java.io.IOException;
import java.net.URL;

import javax.swing.*;
//import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
public class SlideUpdater extends Thread
{
	private Clip clip;
	private String path;
	private MusicStreamer musicStreamer;
	private JSlider progress;
	private boolean suspended;
	private boolean stop;
	
	public SlideUpdater(String xPath, MusicStreamer xMusicStreamer, JSlider xProgress)
	{
		super();
		path = xPath;
		musicStreamer = xMusicStreamer;	
		progress = xProgress;
		suspended = false;
	}
	
	public void run()
	{
		Clip m_clip = null;
		AudioInputStream	audioInputStream = null;
		try
		{
			audioInputStream = AudioSystem.getAudioInputStream(new URL(path));
			AudioInputStream newStream = AudioSystem.getAudioInputStream(musicStreamer.getAudioFormat(), audioInputStream );
	        audioInputStream = newStream;
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
		if (audioInputStream != null)
		{
			DataLine.Info	info = new DataLine.Info(Clip.class, musicStreamer.getAudioFormat());
			try
			{
				m_clip = (Clip) AudioSystem.getLine(info);
				m_clip.open(audioInputStream);				
			}
			catch (LineUnavailableException e)
			{
				e.printStackTrace();
			}	
			catch(IOException e)
			{
				e.printStackTrace();				
			}
		}
		else
		{
		}
		clip = m_clip;
		int length = clip.getFrameLength();
		int posStream;
		double pos;
		while(musicStreamer.getState()!=Thread.State.TERMINATED && !stop )
		{
			synchronized(this) 
			{
                while (suspended && !stop)
                	try
                	{
                		wait();
                	}
                	catch(Exception e)
                	{
                	}
            }
			posStream = musicStreamer.getPosition();
			clip.setFramePosition(posStream);
		    pos = (double) posStream/length;
			progress.setValue((int)(pos*100));
			try
			{
				sleep(100);
			}
			catch(Exception e)
			{
			}
		}
		progress.setValue(0);
	}
	
	public synchronized void pause()
	{
		suspended = !suspended;
		notify();
	}
	
	public synchronized void stop_()
	{
		stop = true;
		notify();
	}

}

Das wäre der Thread, der meinen JSlider updated. Und jetzt kommt der eigentlich abspielende Thread.

PHP:
package pure_mp3;

import java.net.URL;
import java.io.IOException;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.FloatControl;



public class MusicStreamer extends Thread{
	
	private static final int	EXTERNAL_BUFFER_SIZE = 128000;
	private AudioInputStream audioInputStream;
	private SourceDataLine line;
	private AudioFormat audioFormat;
	private DataLine.Info info;
	private Player player;
	private static final double linearScalar = Math.log (10.0)/20;
	private static double volume=100.0;
	private static boolean running = false;
	private boolean pause = false;
	private boolean stop = false;
	
	public MusicStreamer(String path)
	{
		super();	
		insert(path);
	}
	
	public void insert(String path)
	{
		try
		{
			audioInputStream = AudioSystem.getAudioInputStream(new URL(path));
		}
		catch (Exception e)
		{
			e.printStackTrace();
			System.exit(1);
		}		
		if (audioInputStream != null)
		{
			AudioFormat	format = audioInputStream.getFormat();
			if ( format.getEncoding() != AudioFormat.Encoding.PCM_SIGNED ) 
			{
		      // if ((audioFormat.getEncoding() != AudioFormat.Encoding.PCM) ||
		      //     (audioFormat.getEncoding() == AudioFormat.Encoding.ALAW) || 
		      //     (audioFormat.getEncoding() == AudioFormat.Encoding.MP3)) {
		         AudioFormat newFormat = new AudioFormat(
		            AudioFormat.Encoding.PCM_SIGNED, 
		            format.getSampleRate(),
		            16,
		            format.getChannels(),
		            format.getChannels() * 2,
		            format.getSampleRate(),
		            false );
		         AudioInputStream newStream = AudioSystem.getAudioInputStream( newFormat, audioInputStream );
		         format = newFormat;
		         audioInputStream = newStream;
		   }
		}
		audioFormat = audioInputStream.getFormat();
		info = new DataLine.Info(SourceDataLine.class,audioFormat);
		try
		{
			line = (SourceDataLine) AudioSystem.getLine(info);
			line.open(audioFormat);
			line.start();
		}
		catch(Exception e)
		{
			e.printStackTrace();
			System.exit(1);
		}
	}

	public void run()
	{
                running = true;
		setVolume(volume);
		int nBytesRead = 0;
		byte[]	abData = new byte[EXTERNAL_BUFFER_SIZE];
		while (nBytesRead != -1 && !stop)
		{
			synchronized(this) 
			{
                while (pause && !stop)
                	try
                	{
                		wait();
                	}
                	catch(Exception e)
                	{
                	}
            }
			if(!stop)
			{
				try
				{	
					nBytesRead = audioInputStream.read(abData, 0, abData.length);
				}
				catch (IOException e)
				{
					e.printStackTrace();
				}
				if (nBytesRead >= 0 && nBytesRead<=4608)
				{
					line.write(abData, 0, nBytesRead);
				}
			}
		}
		line.drain();
		line.close();
		running = false;
	}
	
	public static boolean getRunning()
	{
		return running;
	}
	
	public synchronized void pause()
	{
		pause = !pause;
		notify();
	}
	
	public synchronized void stop_()
	{
		stop = true;
		notify();
	}
		
	public void setVolume(double xVolume)
	{
		volume = xVolume;
		if( line.isControlSupported( FloatControl.Type.MASTER_GAIN ) ) {
			xVolume = xVolume/100.0d; 
            FloatControl volume = (FloatControl) line.getControl( FloatControl.Type.MASTER_GAIN );
            double minGainDB = volume.getMinimum ();
            double ampGainDB = ( (10.0f/20.0f)*volume.getMaximum ())-volume.getMinimum (); 
            double valueDB = minGainDB+ (1/linearScalar)*Math.log (1+ (Math.exp (linearScalar*ampGainDB)-1)*xVolume);
            volume.setValue((float) valueDB); 
         }
	}
	
	public static void setVolume2(double xVolume)
	{
		volume = xVolume;
	}
	
	public int getPosition()
    {
        return line.getFramePosition();
    }
	
	public AudioFormat getAudioFormat() 
	{
		return audioFormat;
	}
	
	public AudioInputStream getAudioInputStream()
	{
		return audioInputStream;
	}
	
}

Beide Klassen werden von Player verwaltet:

PHP:
package pure_mp3;

/**
 * Write a description of class Player here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */

import javax.swing.JSlider;

public class Player
{
	private static final long serialVersionUID = 20100125;
    private PlayList playlist;
    private Info info;
    private MusicStreamer streamer;
    private SlideUpdater slideUpdater;
    private JSlider progress;
    private boolean playing;
    
    public Player(PlayList xPlaylist, Info xInfo)
    {
        playlist = xPlaylist;
        info = xInfo;
        streamer = null;
        playing = false;
    }
    
    public void prev()
    {
        playlist.prev();
        info.update(); 
        System.out.println("Previous Title: " + playlist.getCurrent());
    }
    
    public void next()
    {
        playlist.next();
        info.update();
        System.out.println("Next Title: " + playlist.getCurrent());
    }
    
	public void play()
    {
		if(!MusicStreamer.getRunning())
		{
			info.update();
			streamer = new MusicStreamer("file:music.mp3");
			slideUpdater = new SlideUpdater("file:music.mp3",streamer,progress);
			playing = !playing;
			streamer.start();
			slideUpdater.start();			
			System.out.println("Play: " + playlist.getCurrent());
		}
		else
		{
//			streamer.stop_();
//			slideUpdater.stop_();
//			streamer = new MusicStreamer("file:music.mp3");
//			slideUpdater = new SlideUpdater("file:music.mp3",streamer,progress);
//			streamer.start();
//			slideUpdater.start();
			streamer.pause();
			slideUpdater.pause();
		}
//			Hiermit kann man hübsch auf das Ende des Abspielens warten
//			new Thread()
//			{
//				public void run()
//				{
//					try
//					{
//						streamer.join();
//						System.out.println("HELLO");
//					}
//					catch(Exception e)
//					{
//					}
//				}
//			}.start();
		}
		
    
    
    public void pause()
    {
        System.out.println("Paused: " + playlist.getCurrent());
    }
    
    public void setPlaying(boolean xPlaying)
    {
    	playing = xPlaying;
    }
    
    public void changeVolume(int xVolume)
    {
        if(playing)
        {
        	streamer.setVolume(xVolume);
        }
        else
        {
        	MusicStreamer.setVolume2(xVolume);
        }
    }
    
    public void setProgress(JSlider xProgress)
    {
    	progress = xProgress;
    }
       
    public SlideUpdater getSlideUpdater()
    {
    	return slideUpdater;
    }
    
    public MusicStreamer getMusicStreamer()
    {
    	return streamer;
    }
    

}

Und letztendlich noch der JSlider.

PHP:
package pure_mp3;

import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class Progress extends JSlider
{
	private static final long serialVersionUID = 2385007980763532219L;
	
	private Player player;
	
	public Progress(Player xPlayer)
	{
		setSize(794,20);
		setMinimum(0);
                setMaximum(100);
                setValue(0);
                player = xPlayer;
                player.setProgress(this);
	}	
}

Hoffe ihr könnt mir helfen.
.
EDIT :
.

Hmmm ich könnte natürlich auch hergehen und mir vom SliderUpdater den Clip geben lassen, sobald dieser erzeugt wurde und dann ganz einfach mit diesem den Rest des Abspielens abhandeln.
 
Zuletzt bearbeitet:
Warum geht eigentlich unter OpenJDK so gut wie gar nichts? Jetzt bin ich zu Ubuntu 10.10 gewechselt und den Code, der unter Windows ohne Probleme lief rüberkopiert und plötzlich kann ich keine Clips erstellen:

Exception in thread "Thread-4" java.lang.NegativeArraySizeException
at org.classpath.icedtea.pulseaudio.PulseAudioClip.open(PulseAudioClip.java:449)
at pure_mp3.StreamSlideUpdater.run(StreamSlideUpdater.java:78)

die Exception fliegt beim öffnen eines Clips.

PHP:
m_clip.open(audioInputStream);
.
EDIT :
.

Sobald ich pulseaudio ausmache, funktioniert alles... Kann ich das irgendwie einbauen, dass nur mein Programm kein pulseaudio benutzt?
 
Nein, kannst du nicht, Pulseaudio ist der Soundserver und damit Herrscher über alle Audioausgaben. Das wäre das selbe, als wenn du versuchen würdest den XServer zu umgehen um dann direkt auf den Bildschirm zu pinseln.

Du solltest lieber dein Programm zurecht biegen, damit es funktioniert. Es sieht ja so aus, als würdest du einen fehlerhaften Parameter übergeben. Ist das Teil Threadsafe, bist du dir sicher, dass du alles richtig übergibst? Manchmal zeigt einem so ein Fehler bei einem Plattformwechsel auch, dass man die ganze Zeit über etwas richtig dummes gemacht hat, was nur aus einem blöden Zufall heraus funktioniert hat.

Solltest du dir sicher sein, dass dein Programm absolut korrekt ist, ist es ratsam sowas als Bug zu melden, damit es hoffentlich bald gefixt wird. Workarounds einbauen ist das sinnloseste, was man auf einem offenen Betriebssystem machen kann. Symptombehandlung statt Ursachenbehandlung wird nur bei Windows betrieben, nicht bei Linux/BSD/Whatever.
 
Joa, okay. Ich bin mir eigentlich ziemlich sicher, dass die pulse-audio Unterstützung unter Linux daran Schuld ist. Ich hab den Sound umgestellt in der sound.properties und siehe da es funktioniert. Könntest du dir den Code mal ansehen, ich glaub ich poste das mal.

Code:
# OpenJDK on Ubuntu is configured to use PulseAudio by default
#javax.sound.sampled.Clip=org.classpath.icedtea.pulseaudio.PulseAudioMixerProvider
#javax.sound.sampled.Port=org.classpath.icedtea.pulseaudio.PulseAudioMixerProvider
#javax.sound.sampled.SourceDataLine=org.classpath.icedtea.pulseaudio.PulseAudioMixerProvider
#javax.sound.sampled.TargetDataLine=org.classpath.icedtea.pulseaudio.PulseAudioMixerProvider

# PulseAudio not running? Please give feedback on LP: #407299.
javax.sound.sampled.Clip=com.sun.media.sound.DirectAudioDeviceProvider
javax.sound.sampled.Port=com.sun.media.sound.PortMixerProvider
javax.sound.sampled.SourceDataLine=com.sun.media.sound.DirectAudioDeviceProvider
javax.sound.sampled.TargetDataLine=com.sun.media.sound.DirectAudioDeviceProvider

EDIT: Ich werde mir das dann aber doch mal anschauen. (bzgl. Threadsafe und so).

So. Hab das ganze jetzt mal überprüft, kann leider nichts finden. Hier mal der Code, den das ganze betrifft:

PHP:
/**

 *  @author Martin Braun

 *  SlideUpdater inspired by Matthias Pfisterer's examples on JavaSound

 *  (jsresources.org). Because of the fact, that this Software is meant 

 *  to be Open-Source and I didn't want to get anybody angry about me 

 *  using parts of his intelligence without mentioning it, I hereby 

 *  mention him as inspiration, because his code helped me to write this class.

 * 

 *  This file is part of pure.mp3.

 *

 *  pure.mp3 is free software: you can redistribute it and/or modify

 *  it under the terms of the GNU General Public License as published by

 *  the Free Software Foundation, either version 3 of the License, or

 *  (at your option) any later version.

 *  

 *  pure.mp3 is distributed in the hope that it will be useful,

 *  but WITHOUT ANY WARRANTY; without even the implied warranty of

 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

 *  GNU General Public License for more details.

 *  

 *  You should have received a copy of the GNU General Public License

 *  along with pure.mp3.  If not, see <http://www.gnu.org/licenses/>.

 */



package pure_mp3;



import java.io.IOException;

import java.net.URL;



//import javax.swing.*;

//import javax.sound.sampled.AudioFormat;

import javax.sound.sampled.AudioInputStream;

import javax.sound.sampled.AudioSystem;

import javax.sound.sampled.Clip;

import javax.sound.sampled.DataLine;

import javax.sound.sampled.LineUnavailableException;



public class StreamSlideUpdater extends Thread implements SlideUpdater
{
    private Clip clip;
    private String path;
    private MusicStreamer musicStreamer;
    private Progress progress;
    private boolean suspended;
    private boolean stop;
    

    public StreamSlideUpdater(String xPath, MusicStreamer xMusicStreamer, Progress xProgress)
    {
        super();
        path = xPath;
        musicStreamer = xMusicStreamer;    
        progress = xProgress;
        suspended = false;
    }

    

    public void run()
    {
        Clip m_clip = null;
        AudioInputStream    audioInputStream = null;
        try
        {

            audioInputStream = AudioSystem.getAudioInputStream(new URL(path));
            AudioInputStream newStream = AudioSystem.getAudioInputStream(musicStreamer.getAudioFormat(), audioInputStream );
            audioInputStream = newStream;

        }

        catch (Exception e)

        {

            e.printStackTrace();

        }

        if (audioInputStream != null)

        {

            DataLine.Info    info = new DataLine.Info(Clip.class, musicStreamer.getAudioFormat());

            try
            {
                m_clip = (Clip) AudioSystem.getLine(info);
//                if(!stop)//Hilft nur gegen Doppelklick
//                {
                    m_clip.open(audioInputStream);    //Hier kommt der Fehler!!!!!!
//                }
            }
            catch (LineUnavailableException e)
            {
                e.printStackTrace();
            }    

            catch(IOException e)
            {
                e.printStackTrace();           
            }

        }

        else

        {

        }

        clip = m_clip;

        int length = clip.getFrameLength();

        int posStream = 0;

        double pos;

        while(musicStreamer.getState()!=Thread.State.TERMINATED && !stop )

        {       
            synchronized(this) 
            {                
                while (suspended && (!stop))
                {
                    try
                    {
                        wait();
                    }
                    catch(Exception e)
                    {
                    }
                }
                notify();
            }
            posStream = musicStreamer.getPosition();
            pos = (double) posStream/length;
            progress.setValue2((int)(pos*100));
            try
            {
                sleep(100);
            }
            catch(Exception e)
            {
            }        
        }    
        progress.setValue(0);        
        clip.drain();
        clip.close();    
    }
    
    public synchronized void pause()
    {
        suspended = !suspended;
        notify();
    }
   
    public synchronized void stop_()
    {
        stop = true;
        notify();
    }
    
    public Clip getClip()
    {
        return clip;
    }
    
    public boolean isStreamSlideUpdater()
    {
        return true;
    }

}

PHP:
/**

 *  @author Martin Braun

 *  MusicPlayer inspired by Matthias Pfisterer's examples on JavaSound

 *  (jsresources.org). Because of the fact, that this Software is meant 

 *  to be Open-Source and I didn't want to get anybody angry about me 

 *  using parts of his intelligence without mentioning it, I hereby 

 *  mention him as inspiration, because his code helped me to write this class.

 * 

 *  This file is part of pure.mp3.

 *

 *  pure.mp3 is free software: you can redistribute it and/or modify

 *  it under the terms of the GNU General Public License as published by

 *  the Free Software Foundation, either version 3 of the License, or

 *  (at your option) any later version.

 *  

 *  pure.mp3 is distributed in the hope that it will be useful,

 *  but WITHOUT ANY WARRANTY; without even the implied warranty of

 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

 *  GNU General Public License for more details.

 *  

 *  You should have received a copy of the GNU General Public License

 *  along with pure.mp3.  If not, see <http://www.gnu.org/licenses/>.

 */



package pure_mp3;



import java.net.URL;

import java.io.IOException;



import javax.sound.sampled.AudioFormat;

import javax.sound.sampled.AudioInputStream;

import javax.sound.sampled.AudioSystem;

import javax.sound.sampled.DataLine;

import javax.sound.sampled.SourceDataLine;

import javax.sound.sampled.FloatControl;





public class MusicStreamer extends Thread implements MusicPlayer

{

	

	private static final int	EXTERNAL_BUFFER_SIZE = 128000;

	private AudioInputStream audioInputStream;

	private SourceDataLine line;

	private AudioFormat audioFormat;

	private DataLine.Info info;

	private Player player;

	public static double volume;

//	private boolean running = false;

	private boolean pause = false;

	private boolean stop = false;

	

	public MusicStreamer(String path, Player xPlayer)

	{

		super();	

		insert(path);

		player = xPlayer;

	}



	public void insert(String path)

	{		

		try

		{

			audioInputStream = AudioSystem.getAudioInputStream(new URL(path));

		}

		catch (Exception e)

		{

			System.out.println("Error while parsing URL to File/Stream");

		}		

		if (audioInputStream != null)

		{

			AudioFormat	format = audioInputStream.getFormat();

			if ( format.getEncoding() != AudioFormat.Encoding.PCM_SIGNED ) 

			{

		         AudioFormat newFormat = new AudioFormat(

		            AudioFormat.Encoding.PCM_SIGNED, 

		            format.getSampleRate(),

		            16,

		            format.getChannels(),

		            format.getChannels() * 2,

		            format.getSampleRate(),

		            false );

		         AudioInputStream newStream = AudioSystem.getAudioInputStream( newFormat, audioInputStream );

		         format = newFormat;

		         audioInputStream = newStream;

		   }

		}

		audioFormat = audioInputStream.getFormat();

		info = new DataLine.Info(SourceDataLine.class,audioFormat);

		try

		{

			line = (SourceDataLine) AudioSystem.getLine(info);

			line.open(audioFormat);

			line.start();

		}

		catch(Exception e)

		{

			System.out.println("Error while starting playback");

		}

	}



	public void run()

	{

//		running = true;

		setVolume(GlobalVars.VOLUME);

		int nBytesRead = 0;

		byte[]	abData = new byte[EXTERNAL_BUFFER_SIZE];

		while (nBytesRead != -1 && !stop)

		{

			synchronized(this) 

			{

                while (pause && !stop)

                {

                	try

                	{

                		wait();

                	}

                	catch(Exception e)

                	{

                	}                	

                }

                notify();

            }

			if(!stop)

			{

				try

				{	

					nBytesRead = audioInputStream.read(abData, 0, abData.length);

				}

				catch (IOException e)

				{

					e.printStackTrace();

				}

				if(nBytesRead != -1);

				{

					line.write(abData, 0, nBytesRead);

				}

			}

		}

		line.drain();

		line.close();

//		running = false;

		if(!stop)

		{

			player.next();

		}

	}

	

//	public synchronized boolean getRunning()

//	{

//		return running;

//	}

	

	public synchronized void pause()

	{

		pause = !pause;

		notify();

	}

	

	public synchronized void stop_()

	{

		stop = true;

		notify();

	}

		

	public void setVolume(double xVolume)

	{

		volume = xVolume;

		GlobalVars.setVolume(xVolume);

		if( line.isControlSupported(FloatControl.Type.MASTER_GAIN)) {

			xVolume = xVolume/100.0d; 

            FloatControl volume = (FloatControl) line.getControl( FloatControl.Type.MASTER_GAIN );

            double minGainDB = volume.getMinimum ();

            double ampGainDB = ((10.0f/20.0f)*volume.getMaximum())-volume.getMinimum(); 

            double valueDB = minGainDB + (1/GlobalVars.LINEARSCALAR)*Math.log (1+ (Math.exp (GlobalVars.LINEARSCALAR*ampGainDB)-1)*xVolume);

            volume.setValue((float) valueDB); 

         }

	}

		

	public int getPosition()

    {

        return line.getFramePosition();

    }

	

	public AudioFormat getAudioFormat() 

	{

		return audioFormat;

	}

	

	public AudioInputStream getAudioInputStream()

	{

		return audioInputStream;

	}

	

	public boolean isMusicStreamer()

	{

		return true;

	}

	

}

Die zweite Klasse ist der eigentlich abspielende Thread.
.
EDIT :
.

Hab noch was gefunden:
Wenn ich das Lied abspiele, kommt am Ende eine IllegalArgumentException bei line.write(abData, 0, nBytesRead); (im MusicPlayer), die kann ich aber abfangen.
 
Zuletzt bearbeitet:
So, ich hab das Problem mit pulseaudio eingegrenzt. Es scheint ein Problem mit mp3spi zu sein. Aber blöderweise bin ich darauf angewiesen... Wie kann ich denn den ServiceProvider nur für mein Programm ändern (sozusagen bevor alles gestartet wird in die main Methode rein?)?
.
EDIT :
.

Scheint so, als wäre meine Idee mit dem Clip zum Anzeigen der Position völlig unsinnig gewesen. Das ganze wird jetzt nochmal neuimplementiert mithilfe der Dokumentation auf jsresources.org
 
Ich habe mal wieder ein Problem, und zwar:

Ich kann nicht von einem extra Thread aus die PlayList verändern, die im Grunde eine JList ist. Weil sobald ich das mache wird die JList weiß und alles stirbt ab. Kann ich irgendwie verhindern, dass neugezeichnet wird? Oder muss ich mir das Model geben lassen, bei JList das Model auf null setzen, dann hinzufügen und dann das Model wieder zurücksetzen?
.
EDIT :
.

Code:
javax.swing.SwingUtilities.invokeLater(new Runnable()
			    		{
			    		    public void run()
			    		    {
			    		    	Global.playList.addSong(new Song(files[j]));
			    		    }
			    		});

Swing Utilites ist unser Freund...
.
EDIT :
.

Man darf nämlich keine Methoden von Swing Komponenten außerhalb des EDT (Event Dispatching Threads) aufrufen.

Quelle: http://stevensrmiller.com/wordpress/?p=567
 
Zurück
Oben Unten