package modules.audio; // переведен

import javax.microedition.lcdui.*;
import javax.microedition.lcdui.game.*;
import javax.microedition.media.*;
import javax.microedition.media.control.*;
import com.vmx.*;
import java.io.*;
import com.one.file.*;
import com.one.*;
import filemanager.MimeType;
import filemanager.images;
import filemanager.main;
import filemanager.options;
import java.util.*;

/**
 * Проигрыватель звуковых файлов
 */
public class cvsPlayer extends gkcCanvas implements PlayerListener, Runnable
{
	public static final String SHUFFLE_PLAY_MARK = "±"; // "°";

	private static Player player;
	private VolumeControl vc;
	private InputStream is;
	private boolean running, paused;
	private Thread t = null;
	private int w, h, w2, h2;
	private int pbx, pby, pbw, pbh; // прогресс
	private String currentFile, OnlyFileName; // tagstr = null;
	private String[] tagstr;
	private int[][] tagstrpos;
	private int tagstrh;
	private AbstractFont infoFont;
	private int pax, pay; // анимация
	private long duration, time, tstep;
	private boolean rtcFlag = false;
	private boolean keyFlag = false;
	private boolean wasPaused = false;
	private int ofnw, ofnx, ofnstep, ofndelay; // прокрутка названия
	private static final int OFN_DEF_DELAY = 1;
	private EqualizerForm eqform;
	private VisualEffect visualfx;
	private AnalogIndicator lai, rai;
    private VolumeUnit lvu, rvu;
    private VolumeUnit[] avu;
    private int vux, lvuy, rvuy, avuy, avuw;
    private int[] avux;
    private int vutarget = 0;
	private PlayList playlist;
	
	private int runpanel; // номер панели, в которой был запущен плеер

	private static cvsPlayer instance;

	public static void loadInstance()
	{
		if(instance == null)
		{
			instance = new cvsPlayer();
		}
	}

	public static cvsPlayer getInstance()
	{
		loadInstance();
		return instance;
	}

	public cvsPlayer()
	{
		setFullScreenMode(true);
		
		w = getWidth();
		h = getHeight();
		
		w2 = w / 2;
		h2 = h / 2;
		
		infoFont = AbstractFont.getFont(AbstractFont.FACE_SYSTEM, AbstractFont.STYLE_BOLD, AbstractFont.SIZE_SMALL);
		
		pax = (w - images.playAnimWidth) / 2;
		pay = (h - images.playAnimHeight) / 2;
		
		pbw = images.playAnimWidth * 3 / 4;
		pbh = infoFont.getHeight() * 3 / 4;
		pbx = (w - pbw) / 2;
		//pby = h - h / 4 - pbh;
		//pby = pay + images.playAnimHeight / 4 + 2;
		pby = (pay + images.playAnimHeight) + (h - images.uiBottomHeight - (pay + images.playAnimHeight) - pbh) / 2;

		lai = new AnalogIndicator(images.playAnimWidth / 2, images.playAnimHeight, images.playAnimWidth * 2 / 5, images.playAnimHeight * 4 / 5, images.playAnimHeight * 5 / 3);
		rai = new AnalogIndicator(images.playAnimWidth / 2, images.playAnimHeight, images.playAnimWidth * 2 / 5, images.playAnimHeight * 4 / 5, images.playAnimHeight * 5 / 3);

        lvu = new VolumeUnit(1, pbw, 8, 35, 2, 3);
        rvu = new VolumeUnit(1, pbw, 8, 35, 2, 3);

        int vspace = (images.playAnimHeight - pbh * 2 + 2) / 3;

        vux = pbx;
        lvuy = pay + vspace;
        rvuy = pay + images.playAnimHeight - pbh - vspace;

        avu = new VolumeUnit[12];
        avux = new int[avu.length];

        avuw = (pbw + avu.length) / (avu.length * 2 - 1);

        int base = pax + (images.playAnimWidth - avuw * (avu.length * 2 - 1)) / 2;

        for(int i = 0; i < avu.length; i++)
        {
            avu[i] = new VolumeUnit(1, pbh * 2 + vspace, 8, 35, 2, 3);
            avux[i] = base + avuw * i * 2;
        }

        avuy = pay + images.playAnimHeight - vspace;
		
		playlist = null;
		runpanel = -1;
		
		try
		{
			eqform = new EqualizerForm(this);
		}
		catch(Throwable t)
		{
			eqform = null;
		}
		
		visualfx = new VisualEffect(12, 15);
	}

	public void setPlayList(PlayList newlist)
	{
		playlist = newlist;
	}

	public void setPlayList(Enumeration newlist)
	{
		playlist = new PlayList(newlist);
	}
	
	protected void initScroll()
	{
		// только имя файла для прокрутки
		OnlyFileName = currentFile.substring(currentFile.lastIndexOf('/') + 1);

		/*
		if(AudioOptions.shufflePlay)
		{
			OnlyFileName += SHUFFLE_PLAY_MARK;
		}
		*/

		ofnw = infoFont.stringWidth(OnlyFileName);
		ofnx = images.uiTopHSpace;
		ofndelay = OFN_DEF_DELAY;
		
		if(ofnw > w - images.uiTopHSpace * 2)
		{
			ofnstep = -(ofnw / OnlyFileName.length());
		}
		else
		{
			ofnstep = 0;
		}
	}
	
	protected void initTag()
	{
		tagstr = new String[0];

		if(player instanceof ModulePlayer)
		{
			tagstr = new String[1];
			tagstr[0] = ((ModulePlayer)player).getSongTitle().trim();
		}
		else if(AudioOptions.metaDataFormat.length() > 0)
		{
			try
			{
				MetaDataControl mdc = (MetaDataControl)player.getControl("MetaDataControl");

				if(mdc != null)
				{
					String[] keys;

					if(AudioOptions.metaDataFormat.equals("*"))
					{
						keys = mdc.getKeys();
					}
					else
					{
						keys = TextProcessor.vectorToStringArray(StringPattern.tokenizeString(AudioOptions.metaDataFormat, ','));
					}

					Vector values = new Vector();
					String value;

					for(int i = 0; i < keys.length; i++)
					{
						value = mdc.getKeyValue(keys[i].trim());

						if(value != null)
						{
							value = value.trim();

							if(value.length() > 0)
							{
								if(AudioOptions.showMetaKeys)
								{
									values.addElement(formatTagKey(keys[i]) + ": " + transcodeTagString(value));
								}
								else
								{
									values.addElement(transcodeTagString(value));
								}
							}
						}
					}

					tagstr = TextProcessor.vectorToStringArray(values);
				}
			}
			catch(Throwable t)
			{
				t.printStackTrace();
			}
		}

		tagstrh = tagstr.length * infoFont.getHeight();
		
		tagstrpos = new int[tagstr.length][2];
		
		for(int i = 0; i < tagstr.length; i++)
		{
			tagstrpos[i][0] = (w - infoFont.stringWidth(tagstr[i])) / 2;
			
			if(tagstrpos[i][0] < 0)
			{
				tagstrpos[i][0] = 0;
			}
			
			tagstrpos[i][1] = images.uiTopHeight + (pay - images.uiTopHeight - tagstrh) / 2 + i * infoFont.getHeight();
		}
	}

	protected static String transcodeTagString(String text)
	{
		text = text.trim();

		byte[] data = StringEncoder.encodeString(text, AudioOptions.id3Enc);
		String res = StringEncoder.decodeString(data, 0, data.length, StringEncoder.ENC_DEFAULT);

		// Проверка: а стоило ли перекодировать-то вообще?

		if(res.length() != text.length())
		{
			return text;
		}

		// Ищем некодируемые символы

		char[] ocs = text.toCharArray();
		char[] rcs = res.toCharArray();

		int count = 0;

		for(int i = 0; i < rcs.length; i++)
		{
			if(rcs[i] == StringEncoder.EMPTY_CHAR &&
			   ocs[i] != StringEncoder.EMPTY_CHAR)
			{
				count++;
			}
		}

		if(count > 0) // rcs.length / 4)
		{
			return text;
		}
		else
		{
			return res;
		}
	}

	protected static String formatTagKey(String key)
	{
		return key.substring(0, 1).toUpperCase() + key.substring(1).toLowerCase();
	}
	
	protected void initDuration()
	{
		duration = player.getDuration();
		tstep = duration / 100;
	}
	
	protected void initPanels()
	{
		if(runpanel < 0)
		{
			runpanel = main.manager.currentPanel();
		}
		
		main.manager.setCurrent(this, runpanel);
		main.manager.updateAssociation(runpanel, playlist.getCurrentElement());
	}
	
	protected void initPlayList(String file)
	{
		currentFile = file;

		if(playlist == null)
		{
			playlist = new PlayList(file);
		}

		playlist.selectElement(file);
	}

	public void playSound(String soundFile)
	{
		destroyPlayer();
		
		initPanels();
		
		player = null;
		running = true;
		rtcFlag = false;
		
		initPlayList(soundFile);
		
		initScroll();
		
		try
		{
			player = Manager.createPlayer("file:///" + soundFile);
			player.realize();
			player.prefetch();

			player.addPlayerListener(this);
			player.setLoopCount(1);

			initDuration();
			
			vc = (VolumeControl)player.getControl("VolumeControl");
			vc.setLevel(AudioOptions.volume);
			vc.setMute(AudioOptions.muted);

			if(eqform != null)
			{
				eqform.init();
			}

			initTag();
		}
		catch(Exception e)
		{
			try
			{
				playSoundFromStream(Connector.openInputStream("file:///" + soundFile), soundFile.substring(soundFile.lastIndexOf('/') + 1));
				return;
			}
			catch(IOException ioe)
			{
				ErrScreen.showErrMsg(11, ioe);
			}
		}
		
		if(t == null)
		{
			t = new Thread(this, "Player/Update");
			t.start();
		}
	}
	
	public void playSoundFromStream(InputStream is, String soundFile)
	{
		destroyPlayer();
		
		initPanels();
		
		player = null;
		running = true;
		rtcFlag = false;
		
		initPlayList(soundFile);
		
		initScroll();
		
		try
		{
			this.is = is;

			try
			{
				player = Manager.createPlayer(is, MimeType.getType(soundFile));
				player.realize();
				player.prefetch();
			}
			catch(Exception stupidEmulatorException)
			{
				player = Manager.createPlayer(is, "audio/mpeg");
				player.realize();
				player.prefetch();
			}

			player.addPlayerListener(this);
			player.setLoopCount(1);
			
			initDuration();
			
			vc =(VolumeControl)player.getControl("VolumeControl");
			vc.setLevel(AudioOptions.volume);
			vc.setMute(AudioOptions.muted);
			
			if(eqform != null)
			{
				eqform.init();
			}

			initTag();
		}
		catch(Exception e)
		{
			ErrScreen.showErrMsg(12, e);
		}
		
		if(t == null)
		{
			t = new Thread(this, "Player/Update");
			t.start();
		}
	}
	
	public void playSoundModule(String soundFile)
	{
		try
		{
			playSoundModuleFromStream(Connector.openInputStream("file:///" + soundFile), soundFile);
		}
		catch(IOException ioe)
		{
			ErrScreen.showErrMsg(13, ioe);
		}
	}
	
	public void playSoundModuleFromStream(InputStream is, String soundFile)
	{
		destroyPlayer();
		
		initPanels();
		
		player = null;
		running = true;
		rtcFlag = false;
		
		initPlayList(soundFile);
		
		initScroll();
		
		try
		{
			this.is = is;
			
			player = new ModulePlayer(is, AudioOptions.modSampleRate, AudioOptions.modQuality, AudioOptions.modBufSize);
			
			player.realize();
			player.prefetch();
			
			player.addPlayerListener(this);
			player.setLoopCount(1);
			
			initDuration();
			
			vc = null;

			((ModulePlayer)player).setVolumeLevel(AudioOptions.volume);
			((ModulePlayer)player).setVolumeMute(AudioOptions.muted);

			if(eqform != null)
			{
				eqform.init();
			}

			initTag();
		}
		catch(Exception e)
		{
			ErrScreen.showErrMsg(12, e);
		}
		
		if(t == null)
		{
			t = new Thread(this, "Player/Update");
			t.start();
		}
	}
	
	public void paint(ExtGraphics g)
	{
		g.setClip(0, 0, w, h);
		
		// Бэкграунд
		if(images.playerUI != null)
		{		
			g.drawImage(images.playerUI, 0, 0, Graphics.LEFT | Graphics.TOP);		
		}
		else
		{
			g.setColor(images.cImgBack);
			g.fillRect(0, 0, w, h);
		}
		
		if(images.buttons != null)
		{
			// Кнопка PLAY
			g.drawRegion(images.buttons, 0, 0, images.btnWidth, images.btnHeight, Sprite.TRANS_NONE, images.uiBottomHOffset, h - images.uiBottomHeight + images.uiBottomVOffset, Graphics.LEFT | Graphics.TOP);
			
			// Кнопка STOP
			g.drawRegion(images.buttons, images.btnWidth * 2, 0, images.btnWidth, images.btnHeight, Sprite.TRANS_NONE, w - images.btnWidth - images.uiBottomHOffset, h - images.uiBottomHeight + images.uiBottomVOffset, Graphics.LEFT | Graphics.TOP);
		}
		
		g.setColor(images.cPlayFore2);
		//g.setColor(images.playerUI != null ? images.cPlayFore2 : Colors.colors[Colors.fore]);
		
		int y = h - images.uiBottomHeight / 2;
		//int trans = AudioOptions.shufflePlay ? Sprite.TRANS_MIRROR_ROT90 : Sprite.TRANS_NONE;
		
		if(AudioOptions.volume == 0) // вывод значка громкости
		{
			images.drawIcon(g, images.iMute, w2 - images.iconWidth, y - images.iconHeight / 2);
			//g.drawRegion(images.getIcon(images.iMute), 0, 0, images.iconWidth, images.iconHeight, trans, w2 - images.iconWidth, y - images.iconHeight / 2, Graphics.LEFT | Graphics.TOP);
			g.fillRect(w2 + 4, y + 4, 10, 1);
		}
		else
		{
			if(!AudioOptions.muted)
			{
				images.drawIcon(g, images.iNoMute, w2 - images.iconWidth, y - images.iconHeight / 2);
				//g.drawRegion(images.getIcon(images.iNoMute), 0, 0, images.iconWidth, images.iconHeight, trans, w2 - images.iconWidth, y - images.iconHeight / 2, Graphics.LEFT | Graphics.TOP);
			}
			else
			{
				images.drawIcon(g, images.iMute, w2 - images.iconWidth, y - images.iconHeight / 2);
				//g.drawRegion(images.getIcon(images.iMute), 0, 0, images.iconWidth, images.iconHeight, trans, w2 - images.iconWidth, y - images.iconHeight / 2, Graphics.LEFT | Graphics.TOP);
			}
			
			for(int i = 0; i < AudioOptions.volume; i += 25)
			{
				g.fillRect(w2 + 4, y + 3 - (i / 25) * 3, 10, 2);
			}
		}
		
		g.setFont(infoFont);
		
		if(AudioOptions.playerVisualMode != 0)
		{
			if(AudioOptions.playerVisualMode == 2)
			{
				g.setColor(images.cImgBack);
				g.fillRect(0, images.uiTopHeight, w, h - images.uiTopHeight - images.uiBottomHeight);
			}
			
			g.setClip(0, images.uiTopHeight, w, h - images.uiTopHeight - images.uiBottomHeight);
			visualfx.drawVisual(g, 0, images.uiTopHeight, w, h - images.uiTopHeight - images.uiBottomHeight, !paused);
			g.setClip(0, 0, w, h);
		}
		else
		{
			images.drawVGradient(g, images.cVisBack1, images.cVisBack2, pax, pay, images.playAnimWidth, images.playAnimHeight, true);

            if(AudioOptions.playerVisualVariant == 1)
            {
                lai.paint(g, pax, pay, !paused);
                rai.paint(g, pax + images.playAnimWidth / 2, pay, !paused);
            }
            else if(AudioOptions.playerVisualVariant == 2)
            {
                g.setColor(images.cVisArrowCap);

                images.fillVLineRect(g, vux, lvuy, lvu.nextValue(!paused), pbh);
                images.fillVLineRect(g, vux, rvuy, rvu.nextValue(!paused), pbh);
            }
            else if(AudioOptions.playerVisualVariant == 3)
            {
                g.setColor(images.cVisArrowCap);

                for(int i = 0; i < avu.length; i++)
                {
                    images.fillHLineRect(g, avux[i], avuy, avuw, avu[i].nextValue(!paused));
                }
            }

			g.setClip(0, 0, w, h);
			g.setColor(images.cImgBack);
			g.drawRect(pax, pay, images.playAnimWidth - 1, images.playAnimHeight - 1);

//			if(images.playAnim != null)
//			{
//				g.drawRegion(images.playAnim, 0, animFrame * images.playAnimHeight, images.playAnimWidth, images.playAnimHeight, Sprite.TRANS_NONE, pax, pay, Graphics.LEFT | Graphics.TOP);
//			}
		}
		
		g.setColor(images.cPlayFore1);
		//g.setColor(images.playerUI != null ? images.cPlayFore1 : Colors.colors[Colors.fore]);

		if(AudioOptions.shufflePlay)
		{
			g.drawString(SHUFFLE_PLAY_MARK, w - 1, images.uiTopHeight, Graphics.RIGHT | Graphics.TOP);
		}

		if(tagstr != null)
		{
			for(int i = 0; i < tagstr.length; i++)
			{
				g.drawString(tagstr[i], tagstrpos[i][0], tagstrpos[i][1], Graphics.LEFT | Graphics.TOP);
			}
		}

		if(player != null)
		{
			if(!keyFlag)
			{
				time = player.getMediaTime();

				if(time > duration)
				{
					time = duration;
				}
			}

			if(duration > 0 && time >= 0 && AudioOptions.showPlayProgress)
			{
				g.drawRect(pbx, pby, pbw, pbh);
				g.fillRect(pbx + 2, pby + 2, (int)((pbw - 3) * time / duration), pbh - 3);
			}
			else
			{
				g.drawString(AuxClass.mediaTimeToString(time), w2, pby, Graphics.TOP | Graphics.HCENTER);
			}
		}
		else if(rtcFlag)
		{
			g.drawString(AuxClass.getCurrentTime(), w2, pby, Graphics.TOP | Graphics.HCENTER);
		}
		
		if(!paused && images.buttons != null)
		{
			g.drawRegion(images.buttons, images.btnWidth, 0, images.btnWidth, images.btnHeight, Sprite.TRANS_NONE, images.uiBottomHOffset, h - images.uiBottomHeight + images.uiBottomVOffset, Graphics.LEFT | Graphics.TOP);
		}
		
		g.setColor(images.cPlayTitle);
		g.setClip(images.uiTopHSpace, images.uiTopVSpace, w - images.uiTopHSpace * 2, images.uiTopHeight - images.uiTopVSpace);

		if(OnlyFileName != null)
		{
			g.drawString(OnlyFileName, ofnx, images.uiTopVSpace, Graphics.LEFT | Graphics.TOP);
		}
	}
	
	public void playerUpdate(Player player, String event, Object data)
	{
		if(event.equals(PlayerListener.END_OF_MEDIA))
		{
			nextSound();
		}
	}
	
	public void run()
	{
		randomVisual();
		
		if(wasPaused)
		{
			paused = true;
		}
		else
		{
			playerStart();
		}

		long prevtime = System.currentTimeMillis();
		
		while(running) // цикл
		{
			if(System.currentTimeMillis() - prevtime > 300)
			{
				prevtime = System.currentTimeMillis();
		
				if(ofndelay > 0)
				{
					ofndelay--;
				}
				else
				{
					ofnx += ofnstep;
				}
				
				if(ofnstep > 0)
				{
					if(ofnx > images.uiTopHSpace)
					{
						ofnx = images.uiTopHSpace;
						ofnstep = -ofnstep;
						ofndelay = OFN_DEF_DELAY;
					}
				}
				else if(ofnstep < 0)
				{
					if(ofnx < w - images.uiTopHSpace - ofnw)
					{
						ofnx = w - images.uiTopHSpace - ofnw;
						ofnstep = -ofnstep;
						ofndelay = OFN_DEF_DELAY;
					}
				}
				
				if(AudioOptions.useAccelerometer)
				{
					final int delta = main.accelerometer.getDelta(0, 1200);
					
					if(delta != 0)
					{
						Runnable runnable = new Runnable()
						{
							public void run()
							{
								if(delta > 0)
								{
									nextSound();
								}
								else if(delta < 0)
								{
									prevSound();
								}
							}
						};

						(new Thread(runnable, "Player/AccelEvent")).start();
					}
				}
			}
				
			repaint();
			//serviceRepaints();

			try
			{
				Thread.sleep(60);
			}
			catch(InterruptedException ie)
			{
			}
		}
	}
	
	/**
	 * Обработчик нажатия кнопок
	 *
	 * @param key int
	 * @todo Implement this javax.microedition.lcdui.Canvas method
	 */
	public void keyPressed(int key)
	{
		key = remapKey(key);

		if(key == KEY_RSK) // правая софт - выход
		{
			destroyPlayer();
			wasPaused = false;
			
			// Возврат
			//main.manager.setCurrent(main.FileSelect, runpanel);
			main.manager.ret();

			playlist.cancelSearch();
			playlist = null;

			runpanel = -1;

			if(options.unloadModules)
			{
				instance = null;
			}
		}
		else if(key == KEY_CANCEL) // назад или красная - сворачиваемся
		{
			main.manager.minimizePanel();
		}
		else if(player != null)
		{
			if(key == KEY_LSK || key == KEY_FIRE || key == KEY_NUM5) // левая софт или зеленая - пауза\воспроизв.
			{
				if(player.getState() == Player.STARTED)
				{
					playerPause();
					wasPaused = true;
				}
				else if(player.getState() == Player.PREFETCHED)
				{
					playerStart();
					wasPaused = false;
				}
			}
			else if(key == KEY_UP || key == KEY_NUM2) // Volume up
			{
				if(!AudioOptions.muted)
				{
					AudioOptions.volume += 5;

					if(AudioOptions.volume > 100)
					{
						AudioOptions.volume = 100;
					}
					
					if(vc != null)
					{
						vc.setLevel(AudioOptions.volume);
					}
					else if(player instanceof ModulePlayer)
					{
						((ModulePlayer)player).setVolumeLevel(AudioOptions.volume);
					}
				}
			}
			else if(key == KEY_DOWN || key == KEY_NUM8) // Volume down
			{
				if(!AudioOptions.muted)
				{
					AudioOptions.volume -= 5;

					if(AudioOptions.volume < 0)
					{
						AudioOptions.volume = 0;
					}
					
					if(vc != null)
					{
						vc.setLevel(AudioOptions.volume);
					}
					else if(player instanceof ModulePlayer)
					{
						((ModulePlayer)player).setVolumeLevel(AudioOptions.volume);
					}
				}
			}
			else if(key == KEY_DIAL) // Volume mute
			{
				AudioOptions.muted = !AudioOptions.muted;

				if(vc != null)
				{
					vc.setMute(AudioOptions.muted);
				}
				else if(player instanceof ModulePlayer)
				{
					((ModulePlayer)player).setVolumeMute(AudioOptions.muted);
				}
			}
			else if(key == KEY_POUND) // Volume mute
			{
				if(++AudioOptions.playerVisualMode > 2)
				{
					AudioOptions.playerVisualMode = 0;
				}

                randomVisual();
			}
			else if(key == KEY_STAR)
			{
				AudioOptions.shufflePlay = !AudioOptions.shufflePlay;
			}
			else if(key == KEY_NUM0)
			{
				if(eqform != null)
				{
					main.dsp.setCurrent(eqform);
				}
			}
			else if(key == KEY_NUM1)
			{
				prevVisual();
			}
			else if(key == KEY_NUM3)
			{
				nextVisual();
			}
			else if(key == KEY_NUM7)
			{
                if(AudioOptions.playerVisualMode == 0)
                {
                    if(paused)
                    {
                        visualSetTarget(vutarget - 1);
                    }
                }
                else
                {
                    visualfx.prevColor();
                }
			}
			else if(key == KEY_NUM9)
			{
                if(AudioOptions.playerVisualMode == 0)
                {
                    if(paused)
                    {
                        visualSetTarget(vutarget + 1);
                    }
                }
                else
                {
                    visualfx.nextColor();
                }
			}
		}
	}
	
	public void keyReleased(int key)
	{
		key = remapKey(key);

		if(keyFlag)
		{
			try
			{
				player.setMediaTime(time);
			}
			catch(MediaException me)
			{
			}

			if(!wasPaused)
			{
				playerStart();
			}
			
			keyFlag = false;
		}
		else
		{
			if((key == KEY_RIGHT) || (key == KEY_NUM6)) // следующий звук
			{
				nextSound();
			}
			else if((key == KEY_LEFT) || (key == KEY_NUM4)) // предыдущий звук
			{
				prevSound();
			}
		}
	}
	
	public void keyRepeated(int key)
	{
		key = remapKey(key);

		if((key == KEY_RIGHT) || (key == KEY_NUM6)) // перемотка вперед
		{
			if(!keyFlag)
			{
				if(!wasPaused)
				{
					playerPause();
				}

				keyFlag = true;
			}

			time += tstep;

			if(time > duration)
			{
				time = duration;
			}
		}
		else if((key == KEY_LEFT) || (key == KEY_NUM4)) // перемотка назад
		{
			if(!keyFlag)
			{
				playerPause();
				keyFlag = true;
			}

			time -= tstep;

			if(time < 0)
			{
				time = 0;
			}
		}
		else
		{
			keyPressed(key);
		}
	}
	
	private void destroyPlayer()
	{
        visualSetValue(0);
        
		OnlyFileName = Locale.getString(this, Locale.WAIT_PLEASE);
		ofnw = 0;
		ofnx = images.uiTopHSpace;
		ofnstep = 0;

		tagstr = null;

		time = 0;

		running = false;
		
		if(t != null)
		{
			if(t.isAlive())
			{
				try
				{
					t.join();
				}
				catch(InterruptedException ie)
				{
				}
			}
			
			t = null;
		}
		
		if(player != null)
		{
			try
			{
				player.stop();
				player.close();
			}
			catch(Exception e)
			{
				//System.out.println ("Cannot stop and exit player");
				//e.printStackTrace ();
			}
			
			player = null;
		}

		if(is != null)
		{
			try
			{
				is.close();
			}
			catch(Exception e)
			{
			}

			is = null;
		}

		main.startLightControl(false);
	}
	
	/**
	 * Останов плеера
	 */
	/*
	private void playerStop()
	{
		if(player == null)
		{
			return;
		}
		
		try
		{
			paused = false;
			player.stop();
			player.setMediaTime(0);
			repaint();
		}
		catch(Exception e)
		{
			//System.out.println ("Cannot stop player");
			//e.printStackTrace ();
		}
	}
	*/

	/**
	 * Пауза плеера
	 */
	private void playerPause()
	{
		if(player == null)
		{
			return;
		}
		
		try
		{
			player.stop();

			if(player.getState() == Player.PREFETCHED)
			{
				paused = true;
				
                visualSetTarget(0);

				repaint();
			}
		}
		catch(Exception e)
		{
			//System.out.println ("Cannot pause player");
			//e.printStackTrace ();
		}

		main.startLightControl(false);
	}
	
	/**
	 * Запуск плеера
	 */
	private void playerStart()
	{
		if(player == null)
		{
			return;
		}
		
		try
		{
			player.start();

			if(player.getState() == Player.STARTED)
			{
				paused = false;
				repaint();

				main.startLightControl(player instanceof ModulePlayer);
			}
		}
		catch(Exception e)
		{
			ErrScreen.showErrMsg(15, e);
		}
	}
	
	/**
	 * Скроллинг текста TEXT (кол-во символов COUNT)
	 *
	 * @param text String
	 * @param count int
	 * @return String
	 */
	/*
	private String scrollText(String text, int count)
	{
		
		String tmp = text;
		int len = text.length();
		int scr = len - count;
		
		if(len > count)
		{
			tmp = text.substring(scrollPos, scrollPos + count);
			
			if(scrolldirection)
			{
				scrollPos--;
			}
			else
			{
				scrollPos++;
			}
			
			if(scrollPos > scr)
			{
				scrollPos--;
				scrolldirection = !scrolldirection;
			}
			else if(scrollPos < 0)
			{
				scrollPos = 0;
				scrolldirection = !scrolldirection;
			}
		}
		
		return tmp;
	}
	*/

	/**
	 * следующий звук
	 */
	public void nextSound()
	{
		destroyPlayer();

		playlist.nextElement(AudioOptions.shufflePlay && !paused);
		main.FileSelect.executeFile(playlist, null, runpanel);
	}
	
	/**
	 * предыдущий звук
	 */
	public void prevSound()
	{
		destroyPlayer();

		playlist.prevElement(AudioOptions.shufflePlay && !paused);
		main.FileSelect.executeFile(playlist, null, runpanel);
	}
	
	public void nextVisual()
	{
		if(++AudioOptions.playerVisualVariant > (AudioOptions.playerVisualMode == 0 ? 3 : 6))
		{
			AudioOptions.playerVisualVariant = 1;
		}
	}

	public void prevVisual()
	{
		if(--AudioOptions.playerVisualVariant < 1)
		{
			AudioOptions.playerVisualVariant = (AudioOptions.playerVisualMode == 0 ? 3 : 6);
		}
	}

	public void randomVisual()
	{
		AudioOptions.playerVisualVariant = AuxClass.randomFromRange(1, (AudioOptions.playerVisualMode == 0 ? 3 : 6));
	}

    private void visualSetTarget(int value)
    {
        vutarget = value;

        lai.setTarget(value);
        rai.setTarget(value);

        lvu.setTarget(value);
        rvu.setTarget(value);

        for(int i = 0; i < avu.length; i++)
        {
            avu[i].setTarget(value);
        }
    }

    private void visualSetValue(int value)
    {
        vutarget = value;

        lai.setValue(value);
        rai.setValue(value);

        lvu.setValue(value);
        rvu.setValue(value);

        for(int i = 0; i < avu.length; i++)
        {
            avu[i].setValue(value);
        }
    }
	
//	private static void out(String s)
//	{
//		System.out.println("[cvsPlayer] " + s);
//	}
}