/* JEsd
 * Copyright (C) 1999 JCraft Inc.
 *  
 * Written by: 1999 ymnk
 *   
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public License
 * as published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
   
 * This program 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 Library General Public License for more details.
 * 
 * You should have received a copy of the GNU Library General Public
 * License along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

package com.jcraft.jesd;

//import javax.media.sound.midi.*;
//import javax.media.sound.sampled.*;
import javax.sound.midi.*;
import javax.sound.sampled.*;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;

class Sample {
  Client parent;                // the client that spawned sample
  int format;                   // magic int with the format info
  int rate;			// sample rate
  int left_vol_scale;		// volume scaling
  int right_vol_scale;

  int id;                       // id number
  byte[] buffer;                // buffer to hold sound data

  int size;
  int sample_length;		// total buffer length

  int cached_length;		// amount of data cached so far
  int ref_count;		// track players for clean deletion
  boolean erase_when_done;	// track uncache requests
  String name;                  // name of sample for remote control

  Clip clip = null;
  SamplePlayer player = null;

  Sample(Client parent, int format, int rate, int size, String name){
    this.parent=parent;
    this.format=format; 
    this.rate=rate;
    this.size=size;
    this.name=name;
    id=getId();
    add(this);
  }

  void free(){
    if(player!=null) player.kill();
    if(clip!=null)clip.close();
    clip=null;
    name=null;
    buffer=null;
    del(this);
  }

  static private java.util.Vector pool=new java.util.Vector();
  static private int _id=1;
  static synchronized int getId(){ return _id++; }
  static synchronized void resetId(){ _id=1; }
  static synchronized void add(Sample sample){ pool.addElement(sample); }
  static synchronized void del(Sample sample){ pool.removeElement(sample); }
  static synchronized Sample get(int id){
    int size=pool.size();
    Sample sample;
    for(int i=0; i<size; i++){
      sample=(Sample)(pool.elementAt(i));
      if(sample.id==id) return sample;
    }
    return null;
  }
  static synchronized Sample get(String name){
    int size=pool.size();
    Sample sample;
    for(int i=0; i<size; i++){
      sample=(Sample)(pool.elementAt(i));
      if(sample.name.equals(name)) return sample;
    }
    return null;
  }

  void fill(IO io){
    try {
      byte[] header=null;
      if(JEsd.samplePlugin!=null){
        SamplePlugin sp=(SamplePlugin)(JEsd.samplePlugin.newInstance());
        byte[] foo=null;
        try{
          ByteArrayOutputStream baos=new ByteArrayOutputStream();
          foo=new byte[size];
          io.readByte(foo, 0, size);
          ByteArrayInputStream bais=new ByteArrayInputStream(foo);
          sp.play(baos, bais); 
          size=baos.size();
          header=new WAVEFile(format, rate, size).getHeader();
          buffer=new byte[header.length+size];
          System.arraycopy(header, 0, buffer, 0, header.length);
          System.arraycopy(baos.toByteArray(), 0, 
			   buffer, header.length, size);
	}
        catch(PluginException ee){
          header=new WAVEFile(format, rate, size).getHeader();
          buffer=new byte[header.length+size];
          System.arraycopy(header, 0, buffer, 0, header.length);
          System.arraycopy(foo, 0, buffer, header.length, size);
	}
      }
      else{
        header=new WAVEFile(format, rate, size).getHeader();
        buffer=new byte[header.length+size];
        System.arraycopy(header, 0, buffer, 0, header.length);
        io.readByte(buffer, WAVEHeader.HEADERSIZE, size);
      }
      mkClip();
    }
    catch(Exception e){}
  }

  static synchronized void dumpInfo(IO io) throws java.io.IOException{
    int size=pool.size();
    Sample s;
    for(int i=0; i<size; i++){
      s=(Sample)(pool.elementAt(i));
      io.writeInt(s.id);
      io.writeByte(s.name.getBytes());
      io.writeInt(s.rate);
      io.writeInt(s.left_vol_scale);
      io.writeInt(s.right_vol_scale);
      io.writeInt(s.format);
      io.writeInt(s.sample_length);
    }
  }

  boolean mkClip(){
    try {

//      ClassLoader  originalClassLoader = null;
//      try{
//        originalClassLoader=Thread.currentThread().getContextClassLoader();
//	Thread.currentThread().setContextClassLoader(ClassLoader.getSystemClassLoader());
//      }
//      catch(Exception ee){
//        // System.out.println(ee);
//      }

      AudioInputStream stream = 
	AudioSystem.getAudioInputStream(new ByteArrayInputStream(buffer));
      AudioFormat format = stream.getFormat();
      DataLine.Info info = new DataLine.Info(Clip.class,
     //                                        null,
     //                                        null,
     //                                        new Class[0],
                                             format,
                                             (int) stream.getFrameLength());
      clip = (Clip) AudioSystem.getLine(info);
      clip.open(stream);

//      if(originalClassLoader!=null)
//        Thread.currentThread().setContextClassLoader(originalClassLoader);
    } 
    catch(Exception e1) {
      //System.err.println(e1);
      return false;
    }
    return true;
  }
}
