/**
 * Copyright (C) 2004-2011 Jive Software. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.java.sipmack.media;

import net.java.sipmack.common.Log;
import net.java.sipmack.sip.Call;
import net.java.sipmack.sip.NetworkAddressManager;
import net.java.sipmack.sip.SIPConfig;
import org.jitsi.service.libjitsi.LibJitsi;
import org.jitsi.service.neomedia.codec.Constants;
import org.jitsi.service.neomedia.format.MediaFormat;
import org.jitsi.service.neomedia.format.MediaFormatFactory;
import org.jivesoftware.sparkimpl.plugin.phone.JMFInit;
import org.jivesoftware.sparkimpl.settings.local.LocalPreferences;
import org.jivesoftware.sparkimpl.settings.local.SettingsManager;

import javax.media.format.AudioFormat;
import javax.media.format.VideoFormat;
import javax.sdp.*;
import java.io.File;
import java.io.IOException;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Vector;

/**
 * JmfMediaManager using JMF based API.
 * It supports GSM, G711 and G723 codecs.
 * <i>This API only currently works on windows and Mac.</i>
 *
 * @author Thiago Camargo
 */
public class JmfMediaManager {

    private List<AudioFormat> audioFormats = new ArrayList<AudioFormat>();
    private List<VideoFormat> videoFormats = new ArrayList<VideoFormat>();
    protected SdpFactory sdpFactory = SdpFactory.getInstance();

    /**
     * Creates a Media Manager instance
     */
    public JmfMediaManager() {
        setupAudioFormats();
        setupVideoFormats();
    }

    /**
     * Returns a new jingleMediaSession
     *
     * @param audioFormat
     * @param remote
     * @param local
     * @return
     */
    public AudioMediaSession createMediaSession(final MediaFormat audioFormat, final TransportCandidate remote, final TransportCandidate local) {    	
        return new AudioMediaSession(audioFormat, remote, local, SettingsManager.getLocalPreferences().getAudioDevice());
    }

    /**
     * Setup API supported AudioFormats
     */
    private void setupAudioFormats() {

        //audioFormats.add(new AudioFormat(Constants.SPEEX_RTP));
        audioFormats.add(new AudioFormat(Constants.ALAW_RTP));
        audioFormats.add(new AudioFormat(AudioFormat.ULAW_RTP));
        audioFormats.add(new AudioFormat(AudioFormat.GSM_RTP));       
        audioFormats.add(new AudioFormat(AudioFormat.G723_RTP));        
    }

    /**
     * Setup API supported VideoFormats
     */
    private void setupVideoFormats() {
    	videoFormats.add(new VideoFormat(VideoFormat.H261_RTP));
    	videoFormats.add(new VideoFormat(VideoFormat.H263_RTP));
    }
    
    /**
     * Return all supported Payloads for this Manager
     *
     * @return The Payload List
     */
    public List<AudioFormat> getAudioFormats() {
        return audioFormats;
    }
    
    /**
     * Return all supported Payloads for this Manager
     *
     * @return The Payload List
     */
    public List<VideoFormat> getVideoFormats() {
        return videoFormats;
    }

    /**
     * Creates a new VideoMedia Session for a given sdpData
     *
     * @param sdpData
     * @return
     * @throws MediaException
     */
    public VideoMediaSession createVideoMediaSession(String sdpData, int localPort) throws MediaException {
        SessionDescription sessionDescription = null;
        if (sdpData == null) {
            throw new MediaException("The SDP data was null! Cannot open "
                    + "a stream withour an SDP Description!");
        }
        try {
            sessionDescription = sdpFactory
                    .createSessionDescription(sdpData);

        }
        catch (SdpParseException ex) {

            throw new MediaException("Incorrect SDP data!", ex);
        }
        Vector<?> mediaDescriptions;
        try {
            mediaDescriptions = sessionDescription
                    .getMediaDescriptions(true);
        }
        catch (SdpException ex) {
            throw new MediaException(
                    "Failed to extract media descriptions from provided session description!",
                    ex);
        }
        Connection sessionConnection = sessionDescription.getConnection();
        String sessionRemoteAddress = null;
        if (sessionConnection != null) {
            try {
                sessionRemoteAddress = sessionConnection.getAddress();
            }
            catch (SdpParseException ex) {
                throw new MediaException(
                        "Failed to extract the connection address parameter"
                                + "from privided session description", ex);
            }
        }
        int mediaPort = -1;
        boolean atLeastOneTransmitterStarted = false;
        //ArrayList mediaTypes = new ArrayList();
        ArrayList<String> remoteAddresses = new ArrayList<String>();
        // A hashtable that indicates what addresses are different media
        // types
        // coming from.
        Hashtable<String, String> remoteTransmisionDetails = new Hashtable<String, String>();
        // by default everything is supposed to be coming from the address
        // specified in the session (global) connection parameter so store
        // this address for now.
        if (sessionRemoteAddress != null) {
            remoteTransmisionDetails.put("audio", sessionRemoteAddress);
            remoteTransmisionDetails.put("video", sessionRemoteAddress);
        }
        ArrayList<Integer> ports = new ArrayList<Integer>();
        ArrayList<ArrayList<MediaFormat>> formatSets = new ArrayList<ArrayList<MediaFormat>>();
        ArrayList<String> contents = new ArrayList<String>();
        ArrayList<Integer> localPorts = new ArrayList<Integer>();
        for (int i = 0; i < mediaDescriptions.size(); i++) {
            MediaDescription mediaDescription = (MediaDescription) mediaDescriptions
                    .get(i);
            Media media = mediaDescription.getMedia();
            // Media Type
            String mediaType = null;
            try {
                mediaType = media.getMediaType();
            }
            catch (SdpParseException ex) {
                continue;
            }

            // Find ports
            try {
                mediaPort = media.getMediaPort();
                System.out.println("MediaType:" + mediaType + ":" + mediaPort);
            }
            catch (SdpParseException ex) {
                throw (new MediaException(
                        "Failed to extract port for media type ["
                                + mediaType + "]. Ignoring description!",
                        ex));
            }
            
            // Find formats
            Vector<?> sdpFormats = null;
            try {
                sdpFormats = media.getMediaFormats(true);
            }
            catch (SdpParseException ex) {
                throw (new MediaException(
                        "Failed to extract media formats for media type ["
                                + mediaType + "]. Ignoring description!",
                        ex));

            }

            Connection mediaConnection = mediaDescription.getConnection();
            String mediaRemoteAddress = null;
            if (mediaConnection == null) {
                if (sessionConnection == null) {
                    throw new MediaException(
                            "A connection parameter was not present in provided session/media description");
                } else {
                    mediaRemoteAddress = sessionRemoteAddress;
                }
            } else {
                try {
                    mediaRemoteAddress = mediaConnection.getAddress();
                }
                catch (SdpParseException ex) {
                    throw new MediaException(
                            "Failed to extract the connection address parameter"
                                    + "from privided media description", ex);
                }
            }

            // update the remote address for the current media type in case
            // it is specific for this media (i.e. differs from the main
            // connection address)
            remoteTransmisionDetails.put(mediaType, mediaRemoteAddress);
            // START TRANSMISSION
            try {
                remoteAddresses.add(mediaRemoteAddress);
                ports.add(new Integer(mediaPort));
                contents.add(mediaType);

                // Selecting local ports for NAT

                if (mediaType.trim().equals("video"))
                    localPorts.add(Integer.valueOf(22444));
                else if (mediaType.trim().equals("audio"))
                    localPorts.add(Integer.valueOf(localPort));
                else
                    localPorts.add(Integer.valueOf(mediaPort));

                formatSets.add(extractTransmittableJmfFormats(sdpFormats));
            }
            catch (MediaException ex) {
                Log.error("StartMedia", ex);
                throw (new MediaException(
                        "Could not start a transmitter for media type ["
                                + mediaType + "]\nIgnoring media ["
                                + mediaType + "]!", ex));
            }
            atLeastOneTransmitterStarted = true;
        }
        if (atLeastOneTransmitterStarted) {

            TransportCandidate.Fixed remote = new TransportCandidate.Fixed(remoteAddresses.get(0).toString(), (Integer) ports.get(0));
            TransportCandidate.Fixed local = new TransportCandidate.Fixed(NetworkAddressManager.getLocalHost().getHostAddress(), localPort);

            // TODO : FORCED TO JPEG_RTP -> deteced format
            // VideoFormat videoFormat = new VideoFormat((String) (((ArrayList) formatSets.get(0)).get(0)));
            VideoFormat videoFormat = new VideoFormat(VideoFormat.JPEG_RTP);         
            VideoMediaSession videoMediaSession = new VideoMediaSession(videoFormat, remote, local, SettingsManager.getLocalPreferences().getVideoDevice());;

            return videoMediaSession;
        }
        return null;
    }
    
    /**
     * Creates a new AudioMedia Session for a given sdpData
     *
     * @param sdpData
     * @return
     * @throws MediaException
     */
    public AudioMediaSession createAudioMediaSession(String sdpData, int localPort) throws MediaException {
   	 
        SessionDescription sessionDescription = null;
        if (sdpData == null) {
            throw new MediaException("The SDP data was null! Cannot open "
                    + "a stream withour an SDP Description!");
        }
        try {
            sessionDescription = sdpFactory
                    .createSessionDescription(sdpData);

        }
        catch (SdpParseException ex) {

            throw new MediaException("Incorrect SDP data!", ex);
        }
        Vector<?> mediaDescriptions;
        try {
            mediaDescriptions = sessionDescription
                    .getMediaDescriptions(true);
        }
        catch (SdpException ex) {
            throw new MediaException(
                    "Failed to extract media descriptions from provided session description!",
                    ex);
        }
        Connection sessionConnection = sessionDescription.getConnection();
        String sessionRemoteAddress = null;
        if (sessionConnection != null) {
            try {
                sessionRemoteAddress = sessionConnection.getAddress();
            }
            catch (SdpParseException ex) {
                throw new MediaException(
                        "Failed to extract the connection address parameter"
                                + "from privided session description", ex);
            }
        }
        int mediaPort = -1;
        boolean atLeastOneTransmitterStarted = false;
        //ArrayList mediaTypes = new ArrayList();
        ArrayList<String> remoteAddresses = new ArrayList<String>();
        // A hashtable that indicates what addresses are different media
        // types
        // coming from.
        Hashtable<String, String> remoteTransmisionDetails = new Hashtable<String, String>();
        // by default everything is supposed to be coming from the address
        // specified in the session (global) connection parameter so store
        // this address for now.
        if (sessionRemoteAddress != null) {
            remoteTransmisionDetails.put("audio", sessionRemoteAddress);
            remoteTransmisionDetails.put("video", sessionRemoteAddress);
        }
        ArrayList<Integer> ports = new ArrayList<Integer>();
        ArrayList<ArrayList<MediaFormat>> formatSets = new ArrayList<ArrayList<MediaFormat>>();
        ArrayList<String> contents = new ArrayList<String>();
        ArrayList<Integer> localPorts = new ArrayList<Integer>();
        for (int i = 0; i < mediaDescriptions.size(); i++) {
            MediaDescription mediaDescription = (MediaDescription) mediaDescriptions
                    .get(i);
            Media media = mediaDescription.getMedia();
            // Media Type
            String mediaType = null;
            try {
                mediaType = media.getMediaType();
            }
            catch (SdpParseException ex) {
                continue;
            }

            // Find ports
            try {
                mediaPort = media.getMediaPort();
                System.out.println("MediaType:" + mediaType + ":" + mediaPort);

            }
            catch (SdpParseException ex) {
                throw (new MediaException(
                        "Failed to extract port for media type ["
                                + mediaType + "]. Ignoring description!",
                        ex));
            }
            
            // Find formats
            Vector<?> sdpFormats = null;
            try {
                sdpFormats = media.getMediaFormats(true);
            }
            catch (SdpParseException ex) {
                throw (new MediaException(
                        "Failed to extract media formats for media type ["
                                + mediaType + "]. Ignoring description!",
                        ex));

            }

            Connection mediaConnection = mediaDescription.getConnection();
            String mediaRemoteAddress = null;
            if (mediaConnection == null) {
                if (sessionConnection == null) {
                    throw new MediaException(
                            "A connection parameter was not present in provided session/media description");
                } else {
                    mediaRemoteAddress = sessionRemoteAddress;
                }
            } else {
                try {
                    mediaRemoteAddress = mediaConnection.getAddress();
                }
                catch (SdpParseException ex) {
                    throw new MediaException(
                            "Failed to extract the connection address parameter"
                                    + "from privided media description", ex);
                }
            }

            // update the remote address for the current media type in case
            // it is specific for this media (i.e. differs from the main
            // connection address)
            remoteTransmisionDetails.put(mediaType, mediaRemoteAddress);
            // START TRANSMISSION
            try {
                remoteAddresses.add(mediaRemoteAddress);
                ports.add(new Integer(mediaPort));
                contents.add(mediaType);

                // Selecting local ports for NAT

                if (mediaType.trim().equals("video"))
                    localPorts.add(Integer.valueOf(22445));
                else if (mediaType.trim().equals("audio"))
                    localPorts.add(Integer.valueOf(localPort));
                else
                    localPorts.add(Integer.valueOf(mediaPort));


                //formatSets
                 //       .add();
                formatSets
                .add(extractTransmittableJmfFormats(sdpFormats));
            }
            catch (MediaException ex) {
                Log.error("StartMedia", ex);
                throw (new MediaException(
                        "Could not start a transmitter for media type ["
                                + mediaType + "]\nIgnoring media ["
                                + mediaType + "]!", ex));
            }
            atLeastOneTransmitterStarted = true;
        }
        if (atLeastOneTransmitterStarted) {

        	System.out.println("Remote Port: " + ports.get(0));
        	
            TransportCandidate.Fixed remote = new TransportCandidate.Fixed(remoteAddresses.get(0).toString(), (Integer) ports.get(0));
            TransportCandidate.Fixed local = new TransportCandidate.Fixed(NetworkAddressManager.getLocalHost().getHostAddress(), localPort);


            MediaFormat mediaFormat = (formatSets.get(0)).get(0);
//            System.out.println("MediaFormat: " + format);
//            System.out.println("MediaFormat: " + format.getRTPPayloadType());
//            System.out.println("MediaFormat: " + format.getMediaType());
//
//            MediaFormat mediaFormat = LibJitsi.getMediaService().getFormatFactory().createMediaFormat("speex", 8000);
//            System.out.println("MediaFormat: " + mediaFormat);
//            System.out.println("MediaFormat: " + mediaFormat.getRTPPayloadType());
//            System.out.println("MediaFormat: " + mediaFormat.getMediaType());
            AudioMediaSession audioMediaSession = new AudioMediaSession(mediaFormat, remote, local, SettingsManager.getLocalPreferences().getAudioDevice());

            return audioMediaSession;
        }
        return null;
    }

    /**
     * Creates a new AudioReceiverChannel Session for a given sdpData
     *
     * @param localPort localPort
     * @return
     * @throws MediaException
     */
    public AudioReceiverChannel createAudioReceiverChannel(int localPort, String remoteIp, int remotePort, int remoteRTCPPort) throws MediaException {

        AudioReceiverChannel audioReceiverChannel = new AudioReceiverChannel(NetworkAddressManager.getLocalHost().getHostAddress(), localPort, remoteIp, remotePort,remoteRTCPPort);

        return audioReceiverChannel;

    }

    /**
     * Extract the supported formats for JMF from a Vector
     *
     * @param sdpFormats
     * @return
     * @throws MediaException
     */
    protected ArrayList<MediaFormat> extractTransmittableJmfFormats(Vector<?> sdpFormats)
            throws MediaException {
        ArrayList<MediaFormat> jmfFormats = new ArrayList<MediaFormat>();
        for (int i = 0; i < sdpFormats.size(); i++) {
    		System.out.println("Add1 ++++++++++++++++++" + sdpFormats);

    		if (Integer.parseInt((String)sdpFormats.get(0)) == 31)
    		{
        		System.out.println(sdpFormats.get(0));
    			MediaFormat videoformat = LibJitsi.getMediaService().getFormatFactory().createMediaFormat(
      	        		"H264",
      	        		 MediaFormatFactory.CLOCK_RATE_NOT_SPECIFIED);
    			jmfFormats.add(videoformat);   
    		}
        	MediaFormat mediaFormat = AudioFormatUtils.findCorrespondingJmfFormat(sdpFormats
                    .elementAt(i).toString());
            if (mediaFormat != null) {
        		System.out.println("Add2 ++++++++++++++++++" + mediaFormat);
                jmfFormats.add(mediaFormat);     
            }
        }
        if (jmfFormats.size() == 0) {
            throw new MediaException(
                    "None of the supplied sdp formats for is supported by SIP COMMUNICATOR");
        }
        return jmfFormats;
    }

    public SessionDescription generateSdpDescription() throws MediaException {
        try {
            SessionDescription sessDescr = sdpFactory
                    .createSessionDescription();

            int audioPort, videoPort;

            audioPort = (int) (5000 * Math.random()) + 5000;
            if (audioPort % 2 != 0) audioPort++;
            do {
                videoPort = (int) (5000 * Math.random()) + 5000;
                if (videoPort % 2 != 0) videoPort++;
            }
            while (audioPort == videoPort);

            // videoPort = "22497";
            // audioPort = "16251";

            Version v = sdpFactory.createVersion(0);
            InetSocketAddress publicVideoAddress = NetworkAddressManager
                    .getPublicAddressFor(videoPort);
            InetSocketAddress publicAudioAddress = NetworkAddressManager
                    .getPublicAddressFor(audioPort);
            InetAddress publicIpAddress = publicAudioAddress.getAddress();
            String addrType = publicIpAddress instanceof Inet6Address ? "IP6"
                    : "IP4";

            // spaces in the user name mess everything up.
            // bug report - Alessandro Melzi
            Origin o = sdpFactory.createOrigin(SIPConfig.getUserName()
                    .replace(' ', '_'), 20109217, 2, "IN", addrType,
                    publicIpAddress.getHostAddress());
            // "s=-"
            SessionName s = sdpFactory.createSessionName("<SIPmack>");
            // c=
            Connection c = sdpFactory.createConnection("IN", addrType,
                    publicIpAddress.getHostAddress());
            // "t=0 0"
            TimeDescription t = sdpFactory.createTimeDescription();
            Vector<TimeDescription> timeDescs = new Vector<TimeDescription>();
            timeDescs.add(t);
            // --------Audio media description
            // make sure preferred formats come first
            String[] aformats = new String[getSelectedFormats().size()];

            int i = 0;
            for (AudioFormat audioFormat : getSelectedFormats()) {
                aformats[i++] = AudioFormatUtils.findCorrespondingSdpFormat(audioFormat.getEncoding());
            }

            MediaDescription am = sdpFactory.createMediaDescription(
                    "audio", publicAudioAddress.getPort(), 1, "RTP/AVP",
                    aformats);
            am.setAttribute("sendrecv", null);
            
            am.setAttribute("rtmap:101", "telephone-event/"
                    + publicAudioAddress.getPort());

            i = 0;
            String[] vformats = new String[getVideoFormats().size()];
            for (VideoFormat videoFormat : getVideoFormats()) {
                vformats[i++] = AudioFormatUtils.findCorrespondingSdpFormat(videoFormat.getEncoding());
            }
            
            MediaDescription vam = sdpFactory.createMediaDescription(
                    "video", publicVideoAddress.getPort(), 1, "RTP/AVP",
                    vformats);
            
            Vector<MediaDescription> mediaDescs = new Vector<MediaDescription>();

            mediaDescs.add(am);
            mediaDescs.add(vam);

            sessDescr.setVersion(v);
            sessDescr.setOrigin(o);
            sessDescr.setConnection(c);
            sessDescr.setSessionName(s);
            sessDescr.setTimeDescriptions(timeDescs);
            if (mediaDescs.size() > 0)
                sessDescr.setMediaDescriptions(mediaDescs);
            return sessDescr;
        }
        catch (SdpException exc) {
            throw new MediaException(
                    "An SDP exception occurred while generating local sdp description",
                    exc);
        }
    }

    /**
     * Generates the Hold Description for a Call.
     *
     * @param setAudio set hold on Audio.
     * @param setVideo set hold on Video.
     * @param call     the call that you want to hold.
     * @return SessionDescription of a call.
     * @throws MediaException
     */
    public SessionDescription generateHoldSdpDescription(boolean setAudio, boolean setVideo, Call call)
            throws MediaException {
        try {
            SessionDescription sessDescr = sdpFactory
                    .createSessionDescription();

            Version v = sdpFactory.createVersion(0);

            InetSocketAddress publicAudioAddress = NetworkAddressManager
                    .getPublicAddressFor(((MediaDescription) (call.getLocalSdpDescription().getMediaDescriptions(true).get(0))).getMedia().getMediaPort());
            InetAddress publicIpAddress = publicAudioAddress.getAddress();
            String addrType = publicIpAddress instanceof Inet6Address ? "IP6"
                    : "IP4";

            Origin o = sdpFactory.createOrigin(SIPConfig.getUserName()
                    .replace(' ', '_'), 20109217, 2, "IN", addrType,
                    publicIpAddress.getHostAddress());
            SessionName s = sdpFactory.createSessionName("<SparkPhone>");
            Connection c = sdpFactory.createConnection("IN", addrType,
                    publicIpAddress.getHostAddress());
            TimeDescription t = sdpFactory.createTimeDescription();
            Vector<TimeDescription> timeDescs = new Vector<TimeDescription>();
            timeDescs.add(t);
            String[] formats = new String[getAudioFormats().size()];

            int i = 0;
            for (AudioFormat audioFormat : getAudioFormats()) {
                formats[i++] = AudioFormatUtils.findCorrespondingSdpFormat(audioFormat.getEncoding());
            }

            MediaDescription am = sdpFactory.createMediaDescription(
                    "audio", publicAudioAddress.getPort(), 1, "RTP/AVP",
                    formats);

            am.setAttribute(setAudio ? "sendonly" : "sendrecv", null);

            am.setAttribute("rtmap:101", "telephone-event/"
                    + publicAudioAddress.getPort());

            Vector<MediaDescription> mediaDescs = new Vector<MediaDescription>();

            mediaDescs.add(am);

            sessDescr.setVersion(v);
            sessDescr.setOrigin(o);
            sessDescr.setConnection(c);
            sessDescr.setSessionName(s);
            sessDescr.setTimeDescriptions(timeDescs);
            if (mediaDescs.size() > 0)
                sessDescr.setMediaDescriptions(mediaDescs);
            return sessDescr;
        }
        catch (SdpException exc) {
            throw new MediaException(
                    "An SDP exception occurred while generating local sdp description",
                    exc);
        }
    }

    /**
     * Runs JMFInit the first time the application is started so that capture
     * devices are properly detected and initialized by JMF.
     */
    public static void setupJMF() {
        // .jmf is the place where we store the jmf.properties file used
        // by JMF. if the directory does not exist or it does not contain
        // a jmf.properties file. or if the jmf.properties file has 0 length
        // then this is the first time we're running and should continue to
        // with JMFInit
        String homeDir = System.getProperty("user.home");
        File jmfDir = new File(homeDir, ".jmf");
        String classpath = System.getProperty("java.class.path");
        classpath += System.getProperty("path.separator")
                + jmfDir.getAbsolutePath();
        System.setProperty("java.class.path", classpath);

        if (!jmfDir.exists())
            jmfDir.mkdir();

        File jmfProperties = new File(jmfDir, "jmf.properties");

        if (!jmfProperties.exists()) {
            try {
                jmfProperties.createNewFile();
            }
            catch (IOException ex) {
                System.out.println("Failed to create jmf.properties");
                ex.printStackTrace();
            }
        }

        // if we're running on linux checkout that libjmutil.so is where it
        // should be and put it there.
        runLinuxPreInstall();

        //if (jmfProperties.length() == 0) {
        new JMFInit(null, false);
        //}

    }

    private static void runLinuxPreInstall() {
        // @TODO Implement Linux Pre-Install
    }
    
    /**
     * reads the codec-order from the user-preferences
     * 
     * @return
     */
    //TODO REMOVE
    @SuppressWarnings("unused")
    private AudioFormat getPreferredFormat(ArrayList<String> formate){
   	 LocalPreferences localPreferences = SettingsManager.getLocalPreferences();
   	 // gets the selected order from preferences
   	 String[] codecs = localPreferences.getSelectedCodecs().split("\\^");
   	 
   	 for(String codec: codecs) {
   		 for(String format : formate) {
             if (format != null && format.equalsIgnoreCase(codec))
   				 return new AudioFormat(format);
   		 }
   	 }
   	 // this return shouldn't be executed, but if no codec was found, then use the first
   	 return new AudioFormat(formate.get(0));
    }
    
    private List<AudioFormat> getSelectedFormats(){
   	 List<AudioFormat> format = new ArrayList<AudioFormat>();
   	 List<AudioFormat> all = getAudioFormats();
   	 LocalPreferences localPreferences = SettingsManager.getLocalPreferences();
   	 // gets the selected order from preferences
   	 String[] codecs = localPreferences.getSelectedCodecs().split("\\^");
   	 for(AudioFormat form : all) {
   		 for(String codec: codecs) {
             if (form.getEncoding().equalsIgnoreCase(codec)) {
	   			 format.add(form);
	   		 }
   		 }
   	 }
   	 
   	 System.out.println("FORMATE NEU: " + format);
   	 return format;
    }
}
