package de.toman.milight;

import java.math.BigInteger;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.Mixer.Info;
import javax.sound.sampled.TargetDataLine;

/**
 * With this class you can visualize your music using some group of lights. The
 * lights will change their color and brightness as the music does.
 * 
 * @author Stefan Toman (toman@tum.de)
 */
public class MusicVisualizer {
	/**
	 * The group of lights controlled by this visualizer
	 */
	private Lights lights;

	/**
	 * The line to read the music input from.
	 */
	private TargetDataLine line;

	/**
	 * This constructor creates a new visualizer.
	 * 
	 * @param lights
	 *            the group of lights to be controlled
	 * @param line
	 *            the line to read the music input from
	 */
	public MusicVisualizer(Lights lights, TargetDataLine line) {
		super();
		this.lights = lights;
		this.line = line;
	}

	/**
	 * This function returns the group of lights controlled by this visualizer.
	 * 
	 * @return the group of lights controlled by this visualizer
	 */
	public Lights getLights() {
		return lights;
	}

	/**
	 * This function returns the line to read the music input from.
	 * 
	 * @return the line to read the music input from
	 */
	public TargetDataLine getLine() {
		return line;
	}

	/**
	 * This function returns the default line to listen on. It is searching for
	 * a mixer called "Primary Sound Capture Driver" or returns some line if
	 * none is found with this none. If there is no available line at all it
	 * will return null.
	 * 
	 * @return the line or null if no line is available
	 */
	public static TargetDataLine getDefaultLine() {
		// search for "Primary Sound Capture Driver"
		for (Info mixerInfo : AudioSystem.getMixerInfo()) {
			javax.sound.sampled.Line.Info[] lineInfos = AudioSystem.getMixer(
					mixerInfo).getTargetLineInfo();
			try {
				if (lineInfos.length > 0
						&& mixerInfo.getName().equals(
								"Primary Sound Capture Driver")) {
					return (TargetDataLine) AudioSystem.getLine(lineInfos[0]);
				}
			} catch (LineUnavailableException e) {
				// line unavailable -> ignore mixer
			}
		}

		// search for some other mixer
		for (Info mixerInfo : AudioSystem.getMixerInfo()) {
			javax.sound.sampled.Line.Info[] lineInfos = AudioSystem.getMixer(
					mixerInfo).getTargetLineInfo();
			try {
				if (lineInfos.length > 0) {
					return (TargetDataLine) AudioSystem.getLine(lineInfos[0]);
				}
			} catch (LineUnavailableException e) {
				// line unavailable -> ignore mixer
			}
		}

		// no line found at all
		return null;
	}

	/**
	 * This function converts a raw array of bytes to an integer value. It will
	 * be converted in the corresponding way to the
	 * {@link AudioFormat#isBigEndian()} value of the
	 * {@link MusicVisualizer#line} attribute.
	 * 
	 * @param data
	 *            is the array of values to converted
	 * @return is the integer represented by the byte array
	 */
	public BigInteger convertByteArrayToInteger(byte[] data) {
		// create variables
		BigInteger ret = BigInteger.ZERO;
		BigInteger power = BigInteger.valueOf(256);

		// read all parts
		for (int i = 0; i < data.length; i++) {
			ret = ret.multiply(power).add(
					BigInteger.valueOf(data[line.getFormat().isBigEndian() ? i
							: (data.length - 1 - i)] & 0xff));
		}

		// return
		return ret;
	}
}

@@ -2940,20 +2940,31 @@
  is 
-the
+an
  array 
-of
+containing the
  val
@@ -2970,16 +2970,19 @@
 lues to 
+be 
 converte
@@ -2983,16 +2983,144 @@
 nverted%0A
+%09 * @param offset%0A%09 *            is the number of bytes to skip%0A%09 * @param length%0A%09 *            is the number of bytes to read%0A
 %09 * @ret
@@ -3229,16 +3229,43 @@
 e%5B%5D data
+, int offset,%0A%09%09%09int length
 ) %7B%0A%09%09//
@@ -3407,21 +3407,16 @@
  0; i %3C 
-data.
 length; 
@@ -3434,16 +3434,22 @@
 et = ret
+%0A%09%09%09%09%09
 .multipl
@@ -3460,19 +3460,19 @@
 wer)
-.add(
 %0A%09%09%09%09%09
+.add(
 BigI
@@ -3469,32 +3469,40 @@
 %09.add(BigInteger
+%0A%09%09%09%09%09%09%09
 .valueOf(data%5Bli
@@ -3536,10 +3536,23 @@
 ) ? 
-i%0A
+(i + offset)%0A%09%09
 %09%09%09%09
@@ -3561,13 +3561,17 @@
 %09: (
-data.
+offset + 
 leng
@@ -3626,11 +3626,496 @@
  ret;%0A%09%7D
+%0A%0A%09/**%0A%09 * This function converts a raw array of bytes to an integer value. It will%0A%09 * be converted in the corresponding way to the%0A%09 * %7B@link AudioFormat#isBigEndian()%7D value of the%0A%09 * %7B@link MusicVisualizer#line%7D attribute.%0A%09 * %0A%09 * @param data%0A%09 *            is the array of values to be converted%0A%09 * @return is the integer represented by the byte array%0A%09 */%0A%09public BigInteger convertByteArrayToInteger(byte%5B%5D data) %7B%0A%09%09return convertByteArrayToInteger(data, 0, data.length);%0A%09%7D
 %0A%7D%0A

make endian function more general